diff options
Diffstat (limited to 'include/clang/AST')
30 files changed, 1758 insertions, 894 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 7edf3b3fed..13870116c7 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_AST_ASTCONTEXT_H #define LLVM_CLANG_AST_ASTCONTEXT_H +#include "clang/AST/ASTContextAllocate.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/CanonicalType.h" #include "clang/AST/CommentCommandTraits.h" @@ -2969,8 +2970,8 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) { /// 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. +/// IMPORTANT: These are also declared in clang/AST/ASTContextAllocate.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 @@ -2993,7 +2994,7 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) { /// allocator supports it). /// @return The allocated memory. Could be nullptr. inline void *operator new(size_t Bytes, const clang::ASTContext &C, - size_t Alignment) { + size_t Alignment /* = 8 */) { return C.Allocate(Bytes, Alignment); } @@ -3031,7 +3032,7 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) { /// allocator supports it). /// @return The allocated memory. Could be nullptr. inline void *operator new[](size_t Bytes, const clang::ASTContext& C, - size_t Alignment = 8) { + size_t Alignment /* = 8 */) { return C.Allocate(Bytes, Alignment); } diff --git a/include/clang/AST/ASTContextAllocate.h b/include/clang/AST/ASTContextAllocate.h new file mode 100644 index 0000000000..5b9eed208a --- /dev/null +++ b/include/clang/AST/ASTContextAllocate.h @@ -0,0 +1,38 @@ +//===- ASTContextAllocate.h - ASTContext allocate functions -----*- 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 ASTContext allocation functions separate from the main +// code in ASTContext.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H +#define LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H + +#include <cstddef> + +namespace clang { + +class ASTContext; + +} // namespace clang + +// Defined in ASTContext.h +void *operator new(size_t Bytes, const clang::ASTContext &C, + size_t Alignment = 8); +void *operator new[](size_t Bytes, const clang::ASTContext &C, + size_t Alignment = 8); + +// 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); + +#endif // LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H diff --git a/include/clang/AST/ASTDumperUtils.h b/include/clang/AST/ASTDumperUtils.h index 129c40ce3e..5e62e902b4 100644 --- a/include/clang/AST/ASTDumperUtils.h +++ b/include/clang/AST/ASTDumperUtils.h @@ -14,7 +14,6 @@ #ifndef LLVM_CLANG_AST_ASTDUMPERUTILS_H #define LLVM_CLANG_AST_ASTDUMPERUTILS_H -#include "clang/AST/ASTContext.h" #include "llvm/Support/raw_ostream.h" namespace clang { @@ -23,7 +22,7 @@ namespace clang { // Do not use bold yellow for any text. It is hard to read on white screens. struct TerminalColor { - raw_ostream::Colors Color; + llvm::raw_ostream::Colors Color; bool Bold; }; @@ -38,50 +37,51 @@ struct TerminalColor { // Bold Cyan - ValueColor, DeclNameColor // Decl kind names (VarDecl, FunctionDecl, etc) -static const TerminalColor DeclKindNameColor = {raw_ostream::GREEN, true}; +static const TerminalColor DeclKindNameColor = {llvm::raw_ostream::GREEN, true}; // Attr names (CleanupAttr, GuardedByAttr, etc) -static const TerminalColor AttrColor = {raw_ostream::BLUE, true}; +static const TerminalColor AttrColor = {llvm::raw_ostream::BLUE, true}; // Statement names (DeclStmt, ImplicitCastExpr, etc) -static const TerminalColor StmtColor = {raw_ostream::MAGENTA, true}; +static const TerminalColor StmtColor = {llvm::raw_ostream::MAGENTA, true}; // Comment names (FullComment, ParagraphComment, TextComment, etc) -static const TerminalColor CommentColor = {raw_ostream::BLUE, false}; +static const TerminalColor CommentColor = {llvm::raw_ostream::BLUE, false}; // Type names (int, float, etc, plus user defined types) -static const TerminalColor TypeColor = {raw_ostream::GREEN, false}; +static const TerminalColor TypeColor = {llvm::raw_ostream::GREEN, false}; // Pointer address -static const TerminalColor AddressColor = {raw_ostream::YELLOW, false}; +static const TerminalColor AddressColor = {llvm::raw_ostream::YELLOW, false}; // Source locations -static const TerminalColor LocationColor = {raw_ostream::YELLOW, false}; +static const TerminalColor LocationColor = {llvm::raw_ostream::YELLOW, false}; // lvalue/xvalue -static const TerminalColor ValueKindColor = {raw_ostream::CYAN, false}; +static const TerminalColor ValueKindColor = {llvm::raw_ostream::CYAN, false}; // bitfield/objcproperty/objcsubscript/vectorcomponent -static const TerminalColor ObjectKindColor = {raw_ostream::CYAN, false}; +static const TerminalColor ObjectKindColor = {llvm::raw_ostream::CYAN, false}; // Null statements -static const TerminalColor NullColor = {raw_ostream::BLUE, false}; +static const TerminalColor NullColor = {llvm::raw_ostream::BLUE, false}; // Undeserialized entities -static const TerminalColor UndeserializedColor = {raw_ostream::GREEN, true}; +static const TerminalColor UndeserializedColor = {llvm::raw_ostream::GREEN, + true}; // CastKind from CastExpr's -static const TerminalColor CastColor = {raw_ostream::RED, false}; +static const TerminalColor CastColor = {llvm::raw_ostream::RED, false}; // Value of the statement -static const TerminalColor ValueColor = {raw_ostream::CYAN, true}; +static const TerminalColor ValueColor = {llvm::raw_ostream::CYAN, true}; // Decl names -static const TerminalColor DeclNameColor = {raw_ostream::CYAN, true}; +static const TerminalColor DeclNameColor = {llvm::raw_ostream::CYAN, true}; // Indents ( `, -. | ) -static const TerminalColor IndentColor = {raw_ostream::BLUE, false}; +static const TerminalColor IndentColor = {llvm::raw_ostream::BLUE, false}; class ColorScope { - raw_ostream &OS; + llvm::raw_ostream &OS; const bool ShowColors; public: - ColorScope(raw_ostream &OS, bool ShowColors, TerminalColor Color) + ColorScope(llvm::raw_ostream &OS, bool ShowColors, TerminalColor Color) : OS(OS), ShowColors(ShowColors) { if (ShowColors) OS.changeColor(Color.Color, Color.Bold); @@ -92,90 +92,6 @@ public: } }; -class TextTreeStructure { - raw_ostream &OS; - const bool ShowColors; - - /// Pending[i] is an action to dump an entity at level i. - llvm::SmallVector<std::function<void(bool isLastChild)>, 32> Pending; - - /// Indicates whether we're at the top level. - bool TopLevel = true; - - /// Indicates if we're handling the first child after entering a new depth. - bool FirstChild = true; - - /// Prefix for currently-being-dumped entity. - std::string Prefix; - -public: - /// Add a child of the current node. Calls doAddChild without arguments - template <typename Fn> void addChild(Fn doAddChild) { - // If we're at the top level, there's nothing interesting to do; just - // run the dumper. - if (TopLevel) { - TopLevel = false; - doAddChild(); - while (!Pending.empty()) { - Pending.back()(true); - Pending.pop_back(); - } - Prefix.clear(); - OS << "\n"; - TopLevel = true; - return; - } - - auto dumpWithIndent = [this, doAddChild](bool isLastChild) { - // Print out the appropriate tree structure and work out the prefix for - // children of this node. For instance: - // - // A Prefix = "" - // |-B Prefix = "| " - // | `-C Prefix = "| " - // `-D Prefix = " " - // |-E Prefix = " | " - // `-F Prefix = " " - // G Prefix = "" - // - // Note that the first level gets no prefix. - { - OS << '\n'; - ColorScope Color(OS, ShowColors, IndentColor); - OS << Prefix << (isLastChild ? '`' : '|') << '-'; - this->Prefix.push_back(isLastChild ? ' ' : '|'); - this->Prefix.push_back(' '); - } - - FirstChild = true; - unsigned Depth = Pending.size(); - - doAddChild(); - - // If any children are left, they're the last at their nesting level. - // Dump those ones out now. - while (Depth < Pending.size()) { - Pending.back()(true); - this->Pending.pop_back(); - } - - // Restore the old prefix. - this->Prefix.resize(Prefix.size() - 2); - }; - - if (FirstChild) { - Pending.push_back(std::move(dumpWithIndent)); - } else { - Pending.back()(false); - Pending.back() = std::move(dumpWithIndent); - } - FirstChild = false; - } - - TextTreeStructure(raw_ostream &OS, bool ShowColors) - : OS(OS), ShowColors(ShowColors) {} -}; - } // namespace clang #endif // LLVM_CLANG_AST_ASTDUMPERUTILS_H diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index cbd5c3414b..dbb9cf35dd 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -33,6 +33,7 @@ namespace clang { class ASTContext; +class ASTImporterLookupTable; class CXXBaseSpecifier; class CXXCtorInitializer; class Decl; @@ -80,12 +81,21 @@ class Attr; /// Imports selected nodes from one AST context into another context, /// merging AST nodes where appropriate. class ASTImporter { + friend class ASTNodeImporter; public: using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>; using ImportedCXXBaseSpecifierMap = llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>; private: + + /// Pointer to the import specific lookup table, which may be shared + /// amongst several ASTImporter objects. + /// This is an externally managed resource (and should exist during the + /// lifetime of the ASTImporter object) + /// If not set then the original C/C++ lookup is used. + ASTImporterLookupTable *LookupTable = nullptr; + /// The contexts we're importing to and from. ASTContext &ToContext, &FromContext; @@ -123,9 +133,13 @@ class Attr; /// (which we have already complained about). NonEquivalentDeclSet NonEquivalentDecls; + using FoundDeclsTy = SmallVector<NamedDecl *, 2>; + FoundDeclsTy findDeclsInToCtx(DeclContext *DC, DeclarationName Name); + + void AddToLookupTable(Decl *ToD); + public: - /// Create a new AST importer. - /// + /// \param ToContext The context we'll be importing into. /// /// \param ToFileManager The file manager we'll be importing into. @@ -137,9 +151,14 @@ class Attr; /// \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. + /// + /// \param LookupTable The importer specific lookup table which may be + /// shared amongst several ASTImporter objects. + /// If not set then the original C/C++ lookup is used. ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTContext &FromContext, FileManager &FromFileManager, - bool MinimalImport); + bool MinimalImport, + ASTImporterLookupTable *LookupTable = nullptr); virtual ~ASTImporter(); diff --git a/include/clang/AST/ASTImporterLookupTable.h b/include/clang/AST/ASTImporterLookupTable.h new file mode 100644 index 0000000000..14cafe817d --- /dev/null +++ b/include/clang/AST/ASTImporterLookupTable.h @@ -0,0 +1,75 @@ +//===- ASTImporterLookupTable.h - ASTImporter specific lookup--*- 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 ASTImporterLookupTable class which implements a +// lookup procedure for the import mechanism. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H +#define LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H + +#include "clang/AST/DeclBase.h" // lookup_result +#include "clang/AST/DeclarationName.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" + +namespace clang { + +class ASTContext; +class NamedDecl; +class DeclContext; + +// There are certain cases when normal C/C++ lookup (localUncachedLookup) +// does not find AST nodes. E.g.: +// Example 1: +// template <class T> +// struct X { +// friend void foo(); // this is never found in the DC of the TU. +// }; +// Example 2: +// // The fwd decl to Foo is not found in the lookupPtr of the DC of the +// // translation unit decl. +// // Here we could find the node by doing a traverse throught the list of +// // the Decls in the DC, but that would not scale. +// struct A { struct Foo *p; }; +// This is a severe problem because the importer decides if it has to create a +// new Decl or not based on the lookup results. +// To overcome these cases we need an importer specific lookup table which +// holds every node and we are not interested in any C/C++ specific visibility +// considerations. Simply, we must know if there is an existing Decl in a +// given DC. Once we found it then we can handle any visibility related tasks. +class ASTImporterLookupTable { + + // We store a list of declarations for each name. + // And we collect these lists for each DeclContext. + // We could have a flat map with (DeclContext, Name) tuple as key, but a two + // level map seems easier to handle. + using DeclList = llvm::SmallSetVector<NamedDecl *, 2>; + using NameMap = llvm::SmallDenseMap<DeclarationName, DeclList, 4>; + using DCMap = llvm::DenseMap<DeclContext *, NameMap>; + + void add(DeclContext *DC, NamedDecl *ND); + void remove(DeclContext *DC, NamedDecl *ND); + + DCMap LookupTable; + +public: + ASTImporterLookupTable(TranslationUnitDecl &TU); + void add(NamedDecl *ND); + void remove(NamedDecl *ND); + using LookupResult = DeclList; + LookupResult lookup(DeclContext *DC, DeclarationName Name) const; + void dump(DeclContext *DC) const; + void dump() const; +}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h index 2037796cd5..f8847505bc 100644 --- a/include/clang/AST/ASTStructuralEquivalence.h +++ b/include/clang/AST/ASTStructuralEquivalence.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H #define LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H +#include "clang/AST/DeclBase.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index 80cd6b7007..51de119f08 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -18,6 +18,7 @@ #ifndef LLVM_CLANG_AST_ASTVECTOR_H #define LLVM_CLANG_AST_ASTVECTOR_H +#include "clang/AST/ASTContextAllocate.h" #include "llvm/ADT/PointerIntPair.h" #include <algorithm> #include <cassert> diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 4ee083934c..3a319326d2 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_ATTR_H #define LLVM_CLANG_AST_ATTR_H +#include "clang/AST/ASTContextAllocate.h" // For Attrs.inc #include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" diff --git a/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h index 2087ecc0e7..43ad1c9319 100644 --- a/include/clang/AST/AttrIterator.h +++ b/include/clang/AST/AttrIterator.h @@ -26,25 +26,6 @@ namespace clang { class ASTContext; class Attr; -} // namespace clang - -// 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. using AttrVec = SmallVector<Attr *, 4>; diff --git a/include/clang/AST/AttrVisitor.h b/include/clang/AST/AttrVisitor.h new file mode 100644 index 0000000000..867f9e7ad1 --- /dev/null +++ b/include/clang/AST/AttrVisitor.h @@ -0,0 +1,76 @@ +//===- AttrVisitor.h - Visitor for Attr 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 AttrVisitor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ATTRVISITOR_H +#define LLVM_CLANG_AST_ATTRVISITOR_H + +#include "clang/AST/Attr.h" + +namespace clang { + +namespace attrvisitor { + +/// A simple visitor class that helps create attribute visitors. +template <template <typename> class Ptr, typename ImplClass, + typename RetTy = void, class... ParamTys> +class Base { +public: +#define PTR(CLASS) typename Ptr<CLASS>::type +#define DISPATCH(NAME) \ + return static_cast<ImplClass *>(this)->Visit##NAME(static_cast<PTR(NAME)>(A)) + + RetTy Visit(PTR(Attr) A) { + switch (A->getKind()) { + +#define ATTR(NAME) \ + case attr::NAME: \ + DISPATCH(NAME##Attr); +#include "clang/Basic/AttrList.inc" + } + llvm_unreachable("Attr that isn't part of AttrList.inc!"); + } + + // If the implementation chooses not to implement a certain visit + // method, fall back to the parent. +#define ATTR(NAME) \ + RetTy Visit##NAME##Attr(PTR(NAME##Attr) A) { DISPATCH(Attr); } +#include "clang/Basic/AttrList.inc" + + RetTy VisitAttr(PTR(Attr)) { return RetTy(); } + +#undef PTR +#undef DISPATCH +}; + +} // namespace attrvisitor + +/// A simple visitor class that helps create attribute visitors. +/// +/// This class does not preserve constness of Attr pointers (see +/// also ConstAttrVisitor). +template <typename ImplClass, typename RetTy = void, typename... ParamTys> +class AttrVisitor : public attrvisitor::Base<std::add_pointer, ImplClass, RetTy, + ParamTys...> {}; + +/// A simple visitor class that helps create attribute visitors. +/// +/// This class preserves constness of Attr pointers (see also +/// AttrVisitor). +template <typename ImplClass, typename RetTy = void, typename... ParamTys> +class ConstAttrVisitor + : public attrvisitor::Base<llvm::make_const_ptr, ImplClass, RetTy, + ParamTys...> {}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_ATTRVISITOR_H diff --git a/include/clang/AST/BaseSubobject.h b/include/clang/AST/BaseSubobject.h index 2b702c76b2..8fd4ac69eb 100644 --- a/include/clang/AST/BaseSubobject.h +++ b/include/clang/AST/BaseSubobject.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_BASESUBOBJECT_H #include "clang/AST/CharUnits.h" +#include "clang/AST/DeclCXX.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/type_traits.h" #include <cstdint> diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index 942d08d585..da16987141 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -8,10 +8,15 @@ clang_tablegen(AttrImpl.inc -gen-clang-attr-impl SOURCE ../Basic/Attr.td TARGET ClangAttrImpl) -clang_tablegen(AttrDump.inc -gen-clang-attr-dump +clang_tablegen(AttrTextNodeDump.inc -gen-clang-attr-text-node-dump -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE ../Basic/Attr.td - TARGET ClangAttrDump) + TARGET ClangAttrTextDump) + +clang_tablegen(AttrNodeTraverse.inc -gen-clang-attr-node-traverse + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrTraverse) clang_tablegen(AttrVisitor.inc -gen-clang-attr-ast-visitor -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 3145f35ead..de2765391f 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_DECL_H #include "clang/AST/APValue.h" +#include "clang/AST/ASTContextAllocate.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" @@ -866,8 +867,12 @@ private: unsigned SClass : 3; unsigned TSCSpec : 2; unsigned InitStyle : 2; + + /// Whether this variable is an ARC pseudo-__strong variable; see + /// isARCPseudoStrong() for details. + unsigned ARCPseudoStrong : 1; }; - enum { NumVarDeclBits = 7 }; + enum { NumVarDeclBits = 8 }; protected: enum { NumParameterIndexBits = 8 }; @@ -940,10 +945,6 @@ protected: /// Whether this variable is the for-in loop declaration in Objective-C. unsigned ObjCForDecl : 1; - /// Whether this variable is an ARC pseudo-__strong - /// variable; see isARCPseudoStrong() for details. - unsigned ARCPseudoStrong : 1; - /// Whether this variable is (C++1z) inline. unsigned IsInline : 1; @@ -1349,17 +1350,15 @@ public: NonParmVarDeclBits.ObjCForDecl = FRD; } - /// 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; - } + /// 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. There are 3 cases where this will be set, 1) if + /// the variable is annotated with the objc_externally_retained attribute, 2) + /// if its 'self' in a non-init method, or 3) if its the variable in an for-in + /// loop. + bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; } + void setARCPseudoStrong(bool PS) { VarDeclBits.ARCPseudoStrong = PS; } /// Whether this variable is (C++1z) inline. bool isInline() const { @@ -2327,14 +2326,6 @@ public: getASTContext()); } - /// Returns the WarnUnusedResultAttr that is either declared on this - /// function, or its return type declaration. - const Attr *getUnusedResultAttr() const; - - /// Returns true if this function or its return type has the - /// warn_unused_result attribute. - bool hasUnusedResultAttr() const { return getUnusedResultAttr() != nullptr; } - /// Returns the storage class as written in the source. For the /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 58e01bf0f0..d3357c245d 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -2180,7 +2180,7 @@ public: /// that for the call operator of a lambda closure type, this returns the /// desugared 'this' type (a pointer to the closure type), not the captured /// 'this' type. - QualType getThisType(ASTContext &C) const; + QualType getThisType() const; static QualType getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl); @@ -3918,6 +3918,7 @@ class MSPropertyDecl : public DeclaratorDecl { : DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL), GetterId(Getter), SetterId(Setter) {} + void anchor() override; public: friend class ASTDeclReader; diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index bc10ba42c6..5b57411f97 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -369,6 +369,14 @@ public: NumParams); } + ParmVarDecl *getParamDecl(unsigned Idx) { + assert(Idx < NumParams && "Index out of bounds!"); + return getParams()[Idx]; + } + const ParmVarDecl *getParamDecl(unsigned Idx) const { + return const_cast<ObjCMethodDecl *>(this)->getParamDecl(Idx); + } + /// Sets the method's parameters and selector source locations. /// If the method is implicit (not coming from source) \p SelLocs is /// ignored. diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 9e01c4950d..f6e3d8f300 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -751,6 +751,7 @@ class RedeclarableTemplateDecl : public TemplateDecl, return getMostRecentDecl(); } + void anchor() override; protected: template <typename EntryType> struct SpecEntryTraits { using DeclType = EntryType; diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index d196233de1..62afae23ec 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -729,9 +729,10 @@ public: /// 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); + if (Name.getNameKind() != DeclarationName::CXXConstructorName && + Name.getNameKind() != DeclarationName::CXXDestructorName && + Name.getNameKind() != DeclarationName::CXXConversionFunctionName) + return nullptr; return LocInfo.NamedType.TInfo; } @@ -747,7 +748,8 @@ public: /// 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); + if (Name.getNameKind() != DeclarationName::CXXOperatorName) + return SourceRange(); return SourceRange( SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc), SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc) @@ -766,7 +768,8 @@ public: /// operator name (not the operator keyword). /// Assumes it is a literal operator. SourceLocation getCXXLiteralOperatorNameLoc() const { - assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName); + if (Name.getNameKind() != DeclarationName::CXXLiteralOperatorName) + return SourceLocation(); return SourceLocation:: getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc); } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index d57c45eec0..3de7342882 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -945,7 +945,6 @@ public: class OpaqueValueExpr : public Expr { friend class ASTStmtReader; Expr *SourceExpr; - SourceLocation Loc; public: OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, @@ -959,8 +958,9 @@ public: T->isInstantiationDependentType() || (SourceExpr && SourceExpr->isInstantiationDependent()), false), - SourceExpr(SourceExpr), Loc(Loc) { + SourceExpr(SourceExpr) { setIsUnique(false); + OpaqueValueExprBits.Loc = Loc; } /// Given an expression which invokes a copy constructor --- i.e. a @@ -969,20 +969,19 @@ public: static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr); explicit OpaqueValueExpr(EmptyShell Empty) - : Expr(OpaqueValueExprClass, Empty) { } + : Expr(OpaqueValueExprClass, Empty) {} /// Retrieve the location of this expression. - SourceLocation getLocation() const { return Loc; } + SourceLocation getLocation() const { return OpaqueValueExprBits.Loc; } SourceLocation getBeginLoc() const LLVM_READONLY { - return SourceExpr ? SourceExpr->getBeginLoc() : Loc; + return SourceExpr ? SourceExpr->getBeginLoc() : getLocation(); } SourceLocation getEndLoc() const LLVM_READONLY { - return SourceExpr ? SourceExpr->getEndLoc() : Loc; + return SourceExpr ? SourceExpr->getEndLoc() : getLocation(); } SourceLocation getExprLoc() const LLVM_READONLY { - if (SourceExpr) return SourceExpr->getExprLoc(); - return Loc; + return SourceExpr ? SourceExpr->getExprLoc() : getLocation(); } child_range children() { @@ -1086,20 +1085,10 @@ class DeclRefExpr final void computeDependence(const ASTContext &Ctx); public: - DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T, + DeclRefExpr(const ASTContext &Ctx, 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), DNLoc(LocInfo) { - DeclRefExprBits.HasQualifier = false; - DeclRefExprBits.HasTemplateKWAndArgsInfo = false; - DeclRefExprBits.HasFoundDecl = false; - DeclRefExprBits.HadMultipleCandidates = false; - DeclRefExprBits.RefersToEnclosingVariableOrCapture = - RefersToEnclosingVariableOrCapture; - DeclRefExprBits.Loc = L; - computeDependence(D->getASTContext()); - } + const DeclarationNameLoc &LocInfo = DeclarationNameLoc()); static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, @@ -2405,59 +2394,126 @@ public: /// a subclass for overloaded operator calls that use operator syntax, e.g., /// "str1 + str2" to resolve to a function call. class CallExpr : public Expr { - enum { FN=0, PREARGS_START=1 }; - Stmt **SubExprs; + enum { FN = 0, PREARGS_START = 1 }; + + /// The number of arguments in the call expression. unsigned NumArgs; + + /// The location of the right parenthese. This has a different meaning for + /// the derived classes of CallExpr. SourceLocation RParenLoc; void updateDependenciesFromArg(Expr *Arg); + // CallExpr store some data in trailing objects. However since CallExpr + // is used a base of other expression classes we cannot use + // llvm::TrailingObjects. Instead we manually perform the pointer arithmetic + // and casts. + // + // The trailing objects are in order: + // + // * A single "Stmt *" for the callee expression. + // + // * An array of getNumPreArgs() "Stmt *" for the pre-argument expressions. + // + // * An array of getNumArgs() "Stmt *" for the argument expressions. + // + // Note that we store the offset in bytes from the this pointer to the start + // of the trailing objects. It would be perfectly possible to compute it + // based on the dynamic kind of the CallExpr. However 1.) we have plenty of + // space in the bit-fields of Stmt. 2.) It was benchmarked to be faster to + // compute this once and then load the offset from the bit-fields of Stmt, + // instead of re-computing the offset each time the trailing objects are + // accessed. + + /// Return a pointer to the start of the trailing array of "Stmt *". + Stmt **getTrailingStmts() { + return reinterpret_cast<Stmt **>(reinterpret_cast<char *>(this) + + CallExprBits.OffsetToTrailingObjects); + } + Stmt *const *getTrailingStmts() const { + return const_cast<CallExpr *>(this)->getTrailingStmts(); + } + + /// Map a statement class to the appropriate offset in bytes from the + /// this pointer to the trailing objects. + static unsigned offsetToTrailingObjects(StmtClass SC); + public: enum class ADLCallKind : bool { NotADL, UsesADL }; static constexpr ADLCallKind NotADL = ADLCallKind::NotADL; static constexpr ADLCallKind UsesADL = ADLCallKind::UsesADL; protected: - // These versions of the constructor are for derived classes. - CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, - ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t, - ExprValueKind VK, SourceLocation rparenloc, unsigned MinNumArgs = 0, - ADLCallKind UsesADL = NotADL); - CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef<Expr *> args, - QualType t, ExprValueKind VK, SourceLocation rparenloc, - unsigned MinNumArgs = 0, ADLCallKind UsesADL = NotADL); - CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, - unsigned NumArgs, 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; + /// Build a call expression, assuming that appropriate storage has been + /// allocated for the trailing objects. + CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation RParenLoc, unsigned MinNumArgs, ADLCallKind UsesADL); + + /// Build an empty call expression, for deserialization. + CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, + EmptyShell Empty); + + /// Return the size in bytes needed for the trailing objects. + /// Used by the derived classes to allocate the right amount of storage. + static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs) { + return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *); + } + + Stmt *getPreArg(unsigned I) { + assert(I < getNumPreArgs() && "Prearg access out of range!"); + return getTrailingStmts()[PREARGS_START + I]; + } + const Stmt *getPreArg(unsigned I) const { + assert(I < getNumPreArgs() && "Prearg access out of range!"); + return getTrailingStmts()[PREARGS_START + I]; + } + void setPreArg(unsigned I, Stmt *PreArg) { + assert(I < getNumPreArgs() && "Prearg access out of range!"); + getTrailingStmts()[PREARGS_START + I] = PreArg; } unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } public: - /// Build a call expression. MinNumArgs specifies the minimum number of - /// arguments. The actual number of arguments will be the greater of - /// args.size() and MinNumArgs. - CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t, - ExprValueKind VK, SourceLocation rparenloc, unsigned MinNumArgs = 0, - ADLCallKind UsesADL = NotADL); + /// Create a call expression. Fn is the callee expression, Args is the + /// argument array, Ty is the type of the call expression (which is *not* + /// the return type in general), VK is the value kind of the call expression + /// (lvalue, rvalue, ...), and RParenLoc is the location of the right + /// parenthese in the call expression. MinNumArgs specifies the minimum + /// number of arguments. The actual number of arguments will be the greater + /// of Args.size() and MinNumArgs. This is used in a few places to allocate + /// enough storage for the default arguments. UsesADL specifies whether the + /// callee was found through argument-dependent lookup. + /// + /// Note that you can use CreateTemporary if you need a temporary call + /// expression on the stack. + static CallExpr *Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation RParenLoc, unsigned MinNumArgs = 0, + ADLCallKind UsesADL = NotADL); + + /// Create a temporary call expression with no arguments in the memory + /// pointed to by Mem. Mem must points to at least sizeof(CallExpr) + /// + sizeof(Stmt *) bytes of storage, aligned to alignof(CallExpr): + /// + /// \code{.cpp} + /// llvm::AlignedCharArray<alignof(CallExpr), + /// sizeof(CallExpr) + sizeof(Stmt *)> Buffer; + /// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer.buffer, etc); + /// \endcode + static CallExpr *CreateTemporary(void *Mem, Expr *Fn, QualType Ty, + ExprValueKind VK, SourceLocation RParenLoc, + ADLCallKind UsesADL = NotADL); - /// Build an empty call expression. - CallExpr(const ASTContext &C, unsigned NumArgs, EmptyShell Empty); + /// Create an empty call expression, for deserialization. + static CallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + 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; } + Expr *getCallee() { return cast<Expr>(getTrailingStmts()[FN]); } + const Expr *getCallee() const { return cast<Expr>(getTrailingStmts()[FN]); } + void setCallee(Expr *F) { getTrailingStmts()[FN] = F; } ADLCallKind getADLCallKind() const { return static_cast<ADLCallKind>(CallExprBits.UsesADL); @@ -2467,55 +2523,56 @@ public: } bool usesADL() const { return getADLCallKind() == UsesADL; } - Decl *getCalleeDecl(); + Decl *getCalleeDecl() { return getCallee()->getReferencedDeclOfCallee(); } const Decl *getCalleeDecl() const { - return const_cast<CallExpr*>(this)->getCalleeDecl(); + return getCallee()->getReferencedDeclOfCallee(); } - /// If the callee is a FunctionDecl, return it. Otherwise return 0. - FunctionDecl *getDirectCallee(); + /// If the callee is a FunctionDecl, return it. Otherwise return null. + FunctionDecl *getDirectCallee() { + return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); + } const FunctionDecl *getDirectCallee() const { - return const_cast<CallExpr*>(this)->getDirectCallee(); + return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); } /// getNumArgs - Return the number of actual arguments to this call. - /// unsigned getNumArgs() const { return NumArgs; } /// Retrieve the call arguments. Expr **getArgs() { - return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START); + return reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START + + getNumPreArgs()); } const Expr *const *getArgs() const { - return reinterpret_cast<Expr **>(SubExprs + getNumPreArgs() + - PREARGS_START); + return reinterpret_cast<const Expr *const *>( + getTrailingStmts() + PREARGS_START + getNumPreArgs()); } /// 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]); + assert(Arg < getNumArgs() && "Arg access out of range!"); + return getArgs()[Arg]; } const Expr *getArg(unsigned Arg) const { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); + assert(Arg < getNumArgs() && "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!"); - SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr; + assert(Arg < getNumArgs() && "Arg access out of range!"); + getArgs()[Arg] = ArgExpr; } /// Reduce the number of arguments in this call expression. This is used for /// example during error recovery to drop extra arguments. There is no way /// to perform the opposite because: 1.) We don't track how much storage /// we have for the argument array 2.) This would potentially require growing - /// the argument array, something we cannot support since the arguments will - /// be stored in a trailing array in the future. - /// (TODO: update this comment when this is done). + /// the argument array, something we cannot support since the arguments are + /// stored in a trailing array. void shrinkNumArgs(unsigned NewNumArgs) { - assert((NewNumArgs <= NumArgs) && + assert((NewNumArgs <= getNumArgs()) && "shrinkNumArgs cannot increase the number of arguments!"); NumArgs = NewNumArgs; } @@ -2530,29 +2587,28 @@ public: return const_arg_range(arg_begin(), arg_end()); } - arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); } - arg_iterator arg_end() { - return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); + arg_iterator arg_begin() { + return getTrailingStmts() + PREARGS_START + getNumPreArgs(); } + arg_iterator arg_end() { return arg_begin() + getNumArgs(); } + const_arg_iterator arg_begin() const { - return SubExprs+PREARGS_START+getNumPreArgs(); - } - const_arg_iterator arg_end() const { - return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); + return getTrailingStmts() + PREARGS_START + getNumPreArgs(); } + const_arg_iterator arg_end() const { return arg_begin() + 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()); + ArrayRef<Stmt *> getRawSubExprs() { + return llvm::makeArrayRef(getTrailingStmts(), + PREARGS_START + getNumPreArgs() + getNumArgs()); } /// getNumCommas - Return the number of commas that must have been present in /// this function call. - unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } + unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; } /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID /// of the callee. If not, return 0. @@ -2567,6 +2623,15 @@ public: /// type. QualType getCallReturnType(const ASTContext &Ctx) const; + /// Returns the WarnUnusedResultAttr that is either declared on the called + /// function, or its return type declaration. + const Attr *getUnusedResultAttr(const ASTContext &Ctx) const; + + /// Returns true if this call expression should warn on unused results. + bool hasUnusedResultAttr(const ASTContext &Ctx) const { + return getUnusedResultAttr(Ctx) != nullptr; + } + SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } @@ -2578,7 +2643,7 @@ public: bool isBuiltinAssumeFalse(const ASTContext &Ctx) const; bool isCallToStdMove() const { - const FunctionDecl* FD = getDirectCallee(); + const FunctionDecl *FD = getDirectCallee(); return getNumArgs() == 1 && FD && FD->isInStdNamespace() && FD->getIdentifier() && FD->getIdentifier()->isStr("move"); } @@ -2590,13 +2655,14 @@ public: // Iterators child_range children() { - return child_range(&SubExprs[0], - &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START); + return child_range(getTrailingStmts(), getTrailingStmts() + PREARGS_START + + getNumPreArgs() + getNumArgs()); } const_child_range children() const { - return const_child_range(&SubExprs[0], &SubExprs[0] + NumArgs + - getNumPreArgs() + PREARGS_START); + return const_child_range(getTrailingStmts(), + getTrailingStmts() + PREARGS_START + + getNumPreArgs() + getNumArgs()); } }; @@ -2930,28 +2996,15 @@ public: /// representation in the source code (ExplicitCastExpr's derived /// classes). class CastExpr : public Expr { -public: - using BasePathSizeTy = unsigned int; - static_assert(std::numeric_limits<BasePathSizeTy>::max() >= 16384, - "[implimits] Direct and indirect base classes [16384]."); - -private: Stmt *Op; bool CastConsistency() const; - BasePathSizeTy *BasePathSize(); - const CXXBaseSpecifier * const *path_buffer() const { return const_cast<CastExpr*>(this)->path_buffer(); } CXXBaseSpecifier **path_buffer(); - void setBasePathSize(BasePathSizeTy basePathSize) { - assert(!path_empty() && basePathSize != 0); - *(BasePathSize()) = basePathSize; - } - protected: CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, Expr *op, unsigned BasePathSize) @@ -2972,9 +3025,9 @@ protected: Op(op) { CastExprBits.Kind = kind; CastExprBits.PartOfExplicitCast = false; - CastExprBits.BasePathIsEmpty = BasePathSize == 0; - if (!path_empty()) - setBasePathSize(BasePathSize); + CastExprBits.BasePathSize = BasePathSize; + assert((CastExprBits.BasePathSize == BasePathSize) && + "BasePathSize overflow!"); assert(CastConsistency()); } @@ -2982,9 +3035,9 @@ protected: CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) : Expr(SC, Empty) { CastExprBits.PartOfExplicitCast = false; - CastExprBits.BasePathIsEmpty = BasePathSize == 0; - if (!path_empty()) - setBasePathSize(BasePathSize); + CastExprBits.BasePathSize = BasePathSize; + assert((CastExprBits.BasePathSize == BasePathSize) && + "BasePathSize overflow!"); } public: @@ -3011,13 +3064,9 @@ public: NamedDecl *getConversionFunction() const; typedef CXXBaseSpecifier **path_iterator; - typedef const CXXBaseSpecifier * const *path_const_iterator; - bool path_empty() const { return CastExprBits.BasePathIsEmpty; } - unsigned path_size() const { - if (path_empty()) - return 0U; - return *(const_cast<CastExpr *>(this)->BasePathSize()); - } + typedef const CXXBaseSpecifier *const *path_const_iterator; + bool path_empty() const { return path_size() == 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(); } @@ -3065,13 +3114,8 @@ public: /// @endcode class ImplicitCastExpr final : public CastExpr, - private llvm::TrailingObjects<ImplicitCastExpr, CastExpr::BasePathSizeTy, - CXXBaseSpecifier *> { - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } + private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> { -private: ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, unsigned BasePathLength, ExprValueKind VK) : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { } @@ -3179,8 +3223,7 @@ public: /// (Type)expr. For example: @c (int)f. class CStyleCastExpr final : public ExplicitCastExpr, - private llvm::TrailingObjects<CStyleCastExpr, CastExpr::BasePathSizeTy, - CXXBaseSpecifier *> { + private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> { SourceLocation LPLoc; // the location of the left paren SourceLocation RPLoc; // the location of the right paren @@ -3194,10 +3237,6 @@ class CStyleCastExpr final explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize) : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: static CStyleCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index f39bddb040..6ef837a2fc 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -75,47 +75,46 @@ class TemplateParameterList; /// 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 { - /// The overloaded operator. - OverloadedOperatorKind Operator; +class CXXOperatorCallExpr final : public CallExpr { + friend class ASTStmtReader; + friend class ASTStmtWriter; SourceRange Range; - // Only meaningful for floating point types. - FPOptions FPFeatures; + // CXXOperatorCallExpr has some trailing objects belonging + // to CallExpr. See CallExpr for the details. SourceRange getSourceRangeImpl() const LLVM_READONLY; -public: - friend class ASTStmtReader; - friend class ASTStmtWriter; + CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation OperatorLoc, FPOptions FPFeatures, + ADLCallKind UsesADL); - CXXOperatorCallExpr(ASTContext &C, OverloadedOperatorKind Op, Expr *fn, - ArrayRef<Expr *> args, QualType t, ExprValueKind VK, - SourceLocation operatorloc, FPOptions FPFeatures, - ADLCallKind UsesADL = NotADL) - : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc, - /*MinNumArgs=*/0, UsesADL), - Operator(Op), FPFeatures(FPFeatures) { - Range = getSourceRangeImpl(); - } + CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty); - explicit CXXOperatorCallExpr(ASTContext &C, unsigned NumArgs, - EmptyShell Empty) - : CallExpr(C, CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs, - Empty) {} +public: + static CXXOperatorCallExpr * + Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation OperatorLoc, FPOptions FPFeatures, + ADLCallKind UsesADL = NotADL); - /// Returns the kind of overloaded operator that this - /// expression refers to. - OverloadedOperatorKind getOperator() const { return Operator; } + static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, EmptyShell Empty); + + /// Returns the kind of overloaded operator that this expression refers to. + OverloadedOperatorKind getOperator() const { + return static_cast<OverloadedOperatorKind>( + CXXOperatorCallExprBits.OperatorKind); + } static bool isAssignmentOp(OverloadedOperatorKind Opc) { - return Opc == OO_Equal || Opc == OO_StarEqual || - Opc == OO_SlashEqual || Opc == OO_PercentEqual || - Opc == OO_PlusEqual || Opc == OO_MinusEqual || - Opc == OO_LessLessEqual || Opc == OO_GreaterGreaterEqual || - Opc == OO_AmpEqual || Opc == OO_CaretEqual || - Opc == OO_PipeEqual; + return Opc == OO_Equal || Opc == OO_StarEqual || Opc == OO_SlashEqual || + Opc == OO_PercentEqual || Opc == OO_PlusEqual || + Opc == OO_MinusEqual || Opc == OO_LessLessEqual || + Opc == OO_GreaterGreaterEqual || Opc == OO_AmpEqual || + Opc == OO_CaretEqual || Opc == OO_PipeEqual; } bool isAssignmentOp() const { return isAssignmentOp(getOperator()); } @@ -130,14 +129,15 @@ public: SourceLocation getOperatorLoc() const { return getRParenLoc(); } SourceLocation getExprLoc() const LLVM_READONLY { + OverloadedOperatorKind Operator = getOperator(); return (Operator < OO_Plus || Operator >= OO_Arrow || Operator == OO_PlusPlus || Operator == OO_MinusMinus) ? getBeginLoc() : getOperatorLoc(); } - SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } SourceRange getSourceRange() const { return Range; } static bool classof(const Stmt *T) { @@ -146,14 +146,17 @@ public: // Set the FP contractability status of this operator. Only meaningful for // operations on floating point types. - void setFPFeatures(FPOptions F) { FPFeatures = F; } - - FPOptions getFPFeatures() const { return FPFeatures; } + void setFPFeatures(FPOptions F) { + CXXOperatorCallExprBits.FPFeatures = F.getInt(); + } + FPOptions getFPFeatures() const { + return FPOptions(CXXOperatorCallExprBits.FPFeatures); + } // Get the FP contractability status of this operator. Only meaningful for // operations on floating point types. bool isFPContractableWithinStatement() const { - return FPFeatures.allowFPContractWithinStatement(); + return getFPFeatures().allowFPContractWithinStatement(); } }; @@ -165,16 +168,23 @@ public: /// 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 { +class CXXMemberCallExpr final : public CallExpr { + // CXXMemberCallExpr has some trailing objects belonging + // to CallExpr. See CallExpr for the details. + + CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation RP, unsigned MinNumArgs); + + CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty); + public: - CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t, - ExprValueKind VK, SourceLocation RP, - unsigned MinNumArgs = 0) - : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP, MinNumArgs, - NotADL) {} + static CXXMemberCallExpr *Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation RP, + unsigned MinNumArgs = 0); - CXXMemberCallExpr(ASTContext &C, unsigned NumArgs, EmptyShell Empty) - : CallExpr(C, CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {} + static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + EmptyShell Empty); /// Retrieves the implicit object argument for the member call. /// @@ -206,20 +216,26 @@ public: }; /// Represents a call to a CUDA kernel function. -class CUDAKernelCallExpr : public CallExpr { -private: +class CUDAKernelCallExpr final : public CallExpr { enum { CONFIG, END_PREARG }; + // CUDAKernelCallExpr has some trailing objects belonging + // to CallExpr. See CallExpr for the details. + + CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, SourceLocation RP, + unsigned MinNumArgs); + + CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty); + public: - CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config, - ArrayRef<Expr *> args, QualType t, ExprValueKind VK, - SourceLocation RP, unsigned MinNumArgs = 0) - : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP, - MinNumArgs, NotADL) {} + static CUDAKernelCallExpr *Create(const ASTContext &Ctx, Expr *Fn, + CallExpr *Config, ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, + SourceLocation RP, unsigned MinNumArgs = 0); - CUDAKernelCallExpr(ASTContext &C, unsigned NumArgs, EmptyShell Empty) - : CallExpr(C, CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs, - Empty) {} + static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, EmptyShell Empty); const CallExpr *getConfig() const { return cast_or_null<CallExpr>(getPreArg(CONFIG)); @@ -309,8 +325,7 @@ public: /// \c static_cast<int>(1.0). class CXXStaticCastExpr final : public CXXNamedCastExpr, - private llvm::TrailingObjects<CXXStaticCastExpr, CastExpr::BasePathSizeTy, - CXXBaseSpecifier *> { + private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> { CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, @@ -321,10 +336,6 @@ class CXXStaticCastExpr final explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -350,8 +361,7 @@ public: /// check to determine how to perform the type conversion. class CXXDynamicCastExpr final : public CXXNamedCastExpr, - private llvm::TrailingObjects< - CXXDynamicCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> { + private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> { CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, @@ -362,10 +372,6 @@ class CXXDynamicCastExpr final explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -398,7 +404,6 @@ public: class CXXReinterpretCastExpr final : public CXXNamedCastExpr, private llvm::TrailingObjects<CXXReinterpretCastExpr, - CastExpr::BasePathSizeTy, CXXBaseSpecifier *> { CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, @@ -411,10 +416,6 @@ class CXXReinterpretCastExpr final CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -442,8 +443,7 @@ public: /// value. class CXXConstCastExpr final : public CXXNamedCastExpr, - private llvm::TrailingObjects<CXXConstCastExpr, CastExpr::BasePathSizeTy, - CXXBaseSpecifier *> { + private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> { CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) @@ -453,10 +453,6 @@ class CXXConstCastExpr final explicit CXXConstCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -482,25 +478,30 @@ public: /// /// 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 { +class UserDefinedLiteral final : public CallExpr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + /// The location of a ud-suffix within the literal. SourceLocation UDSuffixLoc; -public: - friend class ASTStmtReader; - friend class ASTStmtWriter; + // UserDefinedLiteral has some trailing objects belonging + // to CallExpr. See CallExpr for the details. - UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr *> Args, - QualType T, ExprValueKind VK, SourceLocation LitEndLoc, - SourceLocation SuffixLoc) - : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc, - /*MinNumArgs=*/0, NotADL), - UDSuffixLoc(SuffixLoc) {} + UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation LitEndLoc, + SourceLocation SuffixLoc); - explicit UserDefinedLiteral(const ASTContext &C, unsigned NumArgs, - EmptyShell Empty) - : CallExpr(C, UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs, Empty) { - } + UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty); + +public: + static UserDefinedLiteral *Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation LitEndLoc, + SourceLocation SuffixLoc); + + static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, EmptyShell Empty); /// The kind of literal operator which is invoked. enum LiteralOperatorKind { @@ -1259,6 +1260,8 @@ public: /// Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { + friend class ASTStmtReader; + public: enum ConstructionKind { CK_Complete, @@ -1268,98 +1271,119 @@ public: }; private: - CXXConstructorDecl *Constructor = nullptr; - SourceLocation Loc; + /// A pointer to the constructor which will be ultimately called. + CXXConstructorDecl *Constructor; + SourceRange ParenOrBraceRange; - unsigned NumArgs : 16; - unsigned Elidable : 1; - unsigned HadMultipleCandidates : 1; - unsigned ListInitialization : 1; - unsigned StdInitListInitialization : 1; - unsigned ZeroInitialization : 1; - unsigned ConstructKind : 2; - Stmt **Args = nullptr; - void setConstructor(CXXConstructorDecl *C) { Constructor = C; } + /// The number of arguments. + unsigned NumArgs; + + // We would like to stash the arguments of the constructor call after + // CXXConstructExpr. However CXXConstructExpr is used as a base class of + // CXXTemporaryObjectExpr which makes the use of llvm::TrailingObjects + // impossible. + // + // Instead we manually stash the trailing object after the full object + // containing CXXConstructExpr (that is either CXXConstructExpr or + // CXXTemporaryObjectExpr). + // + // The trailing objects are: + // + // * An array of getNumArgs() "Stmt *" for the arguments of the + // constructor call. + + /// Return a pointer to the start of the trailing arguments. + /// Defined just after CXXTemporaryObjectExpr. + inline Stmt **getTrailingArgs(); + const Stmt *const *getTrailingArgs() const { + return const_cast<CXXConstructExpr *>(this)->getTrailingArgs(); + } protected: - CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T, - SourceLocation Loc, - CXXConstructorDecl *Ctor, - bool Elidable, - ArrayRef<Expr *> Args, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization, - ConstructionKind ConstructKind, + /// Build a C++ construction expression. + CXXConstructExpr(StmtClass SC, QualType Ty, SourceLocation Loc, + CXXConstructorDecl *Ctor, bool Elidable, + ArrayRef<Expr *> Args, bool HadMultipleCandidates, + bool ListInitialization, bool StdInitListInitialization, + bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); - /// Construct an empty C++ construction expression. - CXXConstructExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), NumArgs(0), Elidable(false), - HadMultipleCandidates(false), ListInitialization(false), - ZeroInitialization(false), ConstructKind(0) {} + /// Build an empty C++ construction expression. + CXXConstructExpr(StmtClass SC, EmptyShell Empty, unsigned NumArgs); + + /// Return the size in bytes of the trailing objects. Used by + /// CXXTemporaryObjectExpr to allocate the right amount of storage. + static unsigned sizeOfTrailingObjects(unsigned NumArgs) { + return NumArgs * sizeof(Stmt *); + } public: - friend class ASTStmtReader; + /// Create a C++ construction expression. + static CXXConstructExpr * + Create(const ASTContext &Ctx, QualType Ty, SourceLocation Loc, + CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args, + bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, + ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); - /// Construct an empty C++ construction expression. - explicit CXXConstructExpr(EmptyShell Empty) - : CXXConstructExpr(CXXConstructExprClass, Empty) {} - - static CXXConstructExpr *Create(const ASTContext &C, QualType T, - SourceLocation Loc, - CXXConstructorDecl *Ctor, - bool Elidable, - ArrayRef<Expr *> Args, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization, - ConstructionKind ConstructKind, - SourceRange ParenOrBraceRange); + /// Create an empty C++ construction expression. + static CXXConstructExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs); /// Get the constructor that this expression will (ultimately) call. CXXConstructorDecl *getConstructor() const { return Constructor; } - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation Loc) { this->Loc = Loc; } + SourceLocation getLocation() const { return CXXConstructExprBits.Loc; } + void setLocation(SourceLocation Loc) { CXXConstructExprBits.Loc = Loc; } /// Whether this construction is elidable. - bool isElidable() const { return Elidable; } - void setElidable(bool E) { Elidable = E; } + bool isElidable() const { return CXXConstructExprBits.Elidable; } + void setElidable(bool E) { CXXConstructExprBits.Elidable = E; } /// 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; } + bool hadMultipleCandidates() const { + return CXXConstructExprBits.HadMultipleCandidates; + } + void setHadMultipleCandidates(bool V) { + CXXConstructExprBits.HadMultipleCandidates = V; + } /// Whether this constructor call was written as list-initialization. - bool isListInitialization() const { return ListInitialization; } - void setListInitialization(bool V) { ListInitialization = V; } + bool isListInitialization() const { + return CXXConstructExprBits.ListInitialization; + } + void setListInitialization(bool V) { + CXXConstructExprBits.ListInitialization = V; + } /// 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; } + bool isStdInitListInitialization() const { + return CXXConstructExprBits.StdInitListInitialization; + } + void setStdInitListInitialization(bool V) { + CXXConstructExprBits.StdInitListInitialization = V; + } /// Whether this construction first requires /// zero-initialization before the initializer is called. - bool requiresZeroInitialization() const { return ZeroInitialization; } + bool requiresZeroInitialization() const { + return CXXConstructExprBits.ZeroInitialization; + } void setRequiresZeroInitialization(bool ZeroInit) { - ZeroInitialization = ZeroInit; + CXXConstructExprBits.ZeroInitialization = ZeroInit; } /// Determine whether this constructor is actually constructing /// a base class (rather than a complete object). ConstructionKind getConstructionKind() const { - return (ConstructionKind)ConstructKind; + return static_cast<ConstructionKind>(CXXConstructExprBits.ConstructionKind); } void setConstructionKind(ConstructionKind CK) { - ConstructKind = CK; + CXXConstructExprBits.ConstructionKind = CK; } using arg_iterator = ExprIterator; @@ -1372,31 +1396,33 @@ public: return const_arg_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; } + arg_iterator arg_begin() { return getTrailingArgs(); } + arg_iterator arg_end() { return arg_begin() + getNumArgs(); } + const_arg_iterator arg_begin() const { return getTrailingArgs(); } + const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); } - Expr **getArgs() { return reinterpret_cast<Expr **>(Args); } + Expr **getArgs() { return reinterpret_cast<Expr **>(getTrailingArgs()); } const Expr *const *getArgs() const { - return const_cast<CXXConstructExpr *>(this)->getArgs(); + return reinterpret_cast<const Expr *const *>(getTrailingArgs()); } + + /// Return the number of arguments to the constructor call. unsigned getNumArgs() const { return NumArgs; } /// Return the specified argument. Expr *getArg(unsigned Arg) { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(Args[Arg]); + assert(Arg < getNumArgs() && "Arg access out of range!"); + return getArgs()[Arg]; } const Expr *getArg(unsigned Arg) const { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(Args[Arg]); + assert(Arg < getNumArgs() && "Arg access out of range!"); + return getArgs()[Arg]; } /// Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { - assert(Arg < NumArgs && "Arg access out of range!"); - Args[Arg] = ArgExpr; + assert(Arg < getNumArgs() && "Arg access out of range!"); + getArgs()[Arg] = ArgExpr; } SourceLocation getBeginLoc() const LLVM_READONLY; @@ -1406,12 +1432,12 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstructExprClass || - T->getStmtClass() == CXXTemporaryObjectExprClass; + T->getStmtClass() == CXXTemporaryObjectExprClass; } // Iterators child_range children() { - return child_range(&Args[0], &Args[0]+NumArgs); + return child_range(getTrailingArgs(), getTrailingArgs() + getNumArgs()); } }; @@ -1492,8 +1518,7 @@ public: /// \endcode class CXXFunctionalCastExpr final : public ExplicitCastExpr, - private llvm::TrailingObjects< - CXXFunctionalCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> { + private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> { SourceLocation LParenLoc; SourceLocation RParenLoc; @@ -1508,10 +1533,6 @@ class CXXFunctionalCastExpr final explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -1557,26 +1578,36 @@ public: /// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr /// }; /// \endcode -class CXXTemporaryObjectExpr : public CXXConstructExpr { - TypeSourceInfo *Type = nullptr; - -public: +class CXXTemporaryObjectExpr final : public CXXConstructExpr { friend class ASTStmtReader; - CXXTemporaryObjectExpr(const ASTContext &C, - CXXConstructorDecl *Cons, - QualType Type, - TypeSourceInfo *TSI, - ArrayRef<Expr *> Args, + // CXXTemporaryObjectExpr has some trailing objects belonging + // to CXXConstructExpr. See the comment inside CXXConstructExpr + // for more details. + + TypeSourceInfo *TSI; + + CXXTemporaryObjectExpr(CXXConstructorDecl *Cons, QualType Ty, + TypeSourceInfo *TSI, ArrayRef<Expr *> Args, SourceRange ParenOrBraceRange, - bool HadMultipleCandidates, - bool ListInitialization, + bool HadMultipleCandidates, bool ListInitialization, bool StdInitListInitialization, bool ZeroInitialization); - explicit CXXTemporaryObjectExpr(EmptyShell Empty) - : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) {} - TypeSourceInfo *getTypeSourceInfo() const { return Type; } + CXXTemporaryObjectExpr(EmptyShell Empty, unsigned NumArgs); + +public: + static CXXTemporaryObjectExpr * + Create(const ASTContext &Ctx, CXXConstructorDecl *Cons, QualType Ty, + TypeSourceInfo *TSI, ArrayRef<Expr *> Args, + SourceRange ParenOrBraceRange, bool HadMultipleCandidates, + bool ListInitialization, bool StdInitListInitialization, + bool ZeroInitialization); + + static CXXTemporaryObjectExpr *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs); + + TypeSourceInfo *getTypeSourceInfo() const { return TSI; } SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY; @@ -1586,6 +1617,14 @@ public: } }; +Stmt **CXXConstructExpr::getTrailingArgs() { + if (auto *E = dyn_cast<CXXTemporaryObjectExpr>(this)) + return reinterpret_cast<Stmt **>(E + 1); + assert((getStmtClass() == CXXConstructExprClass) && + "Unexpected class deriving from CXXConstructExpr!"); + return reinterpret_cast<Stmt **>(this + 1); +} + /// A C++ lambda expression, which produces a function object /// (of unspecified type) that can be invoked later. /// @@ -1832,18 +1871,19 @@ public: class CXXScalarValueInitExpr : public Expr { friend class ASTStmtReader; - SourceLocation RParenLoc; TypeSourceInfo *TypeInfo; public: /// 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(), + SourceLocation RParenLoc) + : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, false, + false, Type->isInstantiationDependentType(), Type->containsUnexpandedParameterPack()), - RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} + TypeInfo(TypeInfo) { + CXXScalarValueInitExprBits.RParenLoc = RParenLoc; + } explicit CXXScalarValueInitExpr(EmptyShell Shell) : Expr(CXXScalarValueInitExprClass, Shell) {} @@ -1852,10 +1892,12 @@ public: return TypeInfo; } - SourceLocation getRParenLoc() const { return RParenLoc; } + SourceLocation getRParenLoc() const { + return CXXScalarValueInitExprBits.RParenLoc; + } SourceLocation getBeginLoc() const LLVM_READONLY; - SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + SourceLocation getEndLoc() const { return getRParenLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXScalarValueInitExprClass; @@ -1869,54 +1911,56 @@ public: /// Represents a new-expression for memory allocation and constructor /// calls, e.g: "new CXXNewExpr(foo)". -class CXXNewExpr : public Expr { +class CXXNewExpr final + : public Expr, + private llvm::TrailingObjects<CXXNewExpr, Stmt *, SourceRange> { friend class ASTStmtReader; friend class ASTStmtWriter; - - /// Contains an optional array size expression, an optional initialization - /// expression, and any number of optional placement arguments, in that order. - Stmt **SubExprs = nullptr; + friend TrailingObjects; /// Points to the allocation function used. FunctionDecl *OperatorNew; - /// Points to the deallocation function used in case of error. May be - /// null. + /// Points to the deallocation function used in case of error. May be null. FunctionDecl *OperatorDelete; /// The allocated type-source information, as written in the source. TypeSourceInfo *AllocatedTypeInfo; - /// If the allocated type was expressed as a parenthesized type-id, - /// the source range covering the parenthesized type-id. - SourceRange TypeIdParens; - /// Range of the entire new expression. SourceRange Range; /// Source-range of a paren-delimited initializer. SourceRange DirectInitRange; - /// Was the usage ::new, i.e. is the global new to be used? - unsigned GlobalNew : 1; - - /// Do we allocate an array? If so, the first SubExpr is the size expression. - unsigned Array : 1; - - /// Should the alignment be passed to the allocation function? - unsigned PassAlignment : 1; - - /// If this is an array allocation, does the usual deallocation - /// function for the allocated type want to know the allocated size? - unsigned UsualArrayDeleteWantsSize : 1; + // CXXNewExpr is followed by several optional trailing objects. + // They are in order: + // + // * An optional "Stmt *" for the array size expression. + // Present if and ony if isArray(). + // + // * An optional "Stmt *" for the init expression. + // Present if and only if hasInitializer(). + // + // * An array of getNumPlacementArgs() "Stmt *" for the placement new + // arguments, if any. + // + // * An optional SourceRange for the range covering the parenthesized type-id + // if the allocated type was expressed as a parenthesized type-id. + // Present if and only if isParenTypeId(). + unsigned arraySizeOffset() const { return 0; } + unsigned initExprOffset() const { return arraySizeOffset() + isArray(); } + unsigned placementNewArgsOffset() const { + return initExprOffset() + hasInitializer(); + } - /// The number of placement new arguments. - unsigned NumPlacementArgs : 26; + unsigned numTrailingObjects(OverloadToken<Stmt *>) const { + return isArray() + hasInitializer() + getNumPlacementArgs(); + } - /// 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; + unsigned numTrailingObjects(OverloadToken<SourceRange>) const { + return isParenTypeId(); + } public: enum InitializationStyle { @@ -1930,18 +1974,35 @@ public: ListInit }; - CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - FunctionDecl *operatorDelete, bool PassAlignment, - 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) {} +private: + /// Build a c++ new expression. + CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, + SourceRange TypeIdParens, Expr *ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); + + /// Build an empty c++ new expression. + CXXNewExpr(EmptyShell Empty, bool IsArray, unsigned NumPlacementArgs, + bool IsParenTypeId); - void AllocateArgsArray(const ASTContext &C, bool isArray, - unsigned numPlaceArgs, bool hasInitializer); +public: + /// Create a c++ new expression. + static CXXNewExpr * + Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, + SourceRange TypeIdParens, Expr *ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); + + /// Create an empty c++ new expression. + static CXXNewExpr *CreateEmpty(const ASTContext &Ctx, bool IsArray, + bool HasInit, unsigned NumPlacementArgs, + bool IsParenTypeId); QualType getAllocatedType() const { assert(getType()->isPointerType()); @@ -1967,58 +2028,74 @@ public: /// 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; + bool shouldNullCheckAllocation() 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; } + bool isArray() const { return CXXNewExprBits.IsArray; } Expr *getArraySize() { - return Array ? cast<Expr>(SubExprs[0]) : nullptr; + return isArray() + ? cast<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]) + : nullptr; } const Expr *getArraySize() const { - return Array ? cast<Expr>(SubExprs[0]) : nullptr; + return isArray() + ? cast<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]) + : nullptr; } - unsigned getNumPlacementArgs() const { return NumPlacementArgs; } + unsigned getNumPlacementArgs() const { + return CXXNewExprBits.NumPlacementArgs; + } Expr **getPlacementArgs() { - return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer()); + return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>() + + placementNewArgsOffset()); } - Expr *getPlacementArg(unsigned i) { - assert(i < NumPlacementArgs && "Index out of range"); - return getPlacementArgs()[i]; + Expr *getPlacementArg(unsigned I) { + assert((I < getNumPlacementArgs()) && "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); + const Expr *getPlacementArg(unsigned I) const { + return const_cast<CXXNewExpr *>(this)->getPlacementArg(I); } - bool isParenTypeId() const { return TypeIdParens.isValid(); } - SourceRange getTypeIdParens() const { return TypeIdParens; } + bool isParenTypeId() const { return CXXNewExprBits.IsParenTypeId; } + SourceRange getTypeIdParens() const { + return isParenTypeId() ? getTrailingObjects<SourceRange>()[0] + : SourceRange(); + } - bool isGlobalNew() const { return GlobalNew; } + bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; } /// Whether this new-expression has any initializer at all. - bool hasInitializer() const { return StoredInitializationStyle > 0; } + bool hasInitializer() const { + return CXXNewExprBits.StoredInitializationStyle > 0; + } /// The kind of initializer this new-expression has. InitializationStyle getInitializationStyle() const { - if (StoredInitializationStyle == 0) + if (CXXNewExprBits.StoredInitializationStyle == 0) return NoInit; - return static_cast<InitializationStyle>(StoredInitializationStyle-1); + return static_cast<InitializationStyle>( + CXXNewExprBits.StoredInitializationStyle - 1); } /// The initializer of this new-expression. Expr *getInitializer() { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; + return hasInitializer() + ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()]) + : nullptr; } const Expr *getInitializer() const { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; + return hasInitializer() + ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()]) + : nullptr; } /// Returns the CXXConstructExpr from this new-expression, or null. @@ -2028,15 +2105,13 @@ public: /// Indicates whether the required alignment should be implicitly passed to /// the allocation function. - bool passAlignment() const { - return PassAlignment; - } + bool passAlignment() const { return CXXNewExprBits.ShouldPassAlignment; } /// 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; + return CXXNewExprBits.UsualArrayDeleteWantsSize; } using arg_iterator = ExprIterator; @@ -2051,47 +2126,43 @@ public: } arg_iterator placement_arg_begin() { - return SubExprs + Array + hasInitializer(); + return getTrailingObjects<Stmt *>() + placementNewArgsOffset(); } arg_iterator placement_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return placement_arg_begin() + getNumPlacementArgs(); } const_arg_iterator placement_arg_begin() const { - return SubExprs + Array + hasInitializer(); + return getTrailingObjects<Stmt *>() + placementNewArgsOffset(); } const_arg_iterator placement_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return placement_arg_begin() + getNumPlacementArgs(); } using raw_arg_iterator = Stmt **; - raw_arg_iterator raw_arg_begin() { return SubExprs; } + raw_arg_iterator raw_arg_begin() { return getTrailingObjects<Stmt *>(); } raw_arg_iterator raw_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>()); + } + const_arg_iterator raw_arg_begin() const { + return getTrailingObjects<Stmt *>(); } - const_arg_iterator raw_arg_begin() const { return SubExprs; } const_arg_iterator raw_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>()); } SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } SourceRange getDirectInitRange() const { return DirectInitRange; } - - SourceRange getSourceRange() const LLVM_READONLY { - return Range; - } - + SourceRange getSourceRange() const { return Range; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNewExprClass; } // Iterators - child_range children() { - return child_range(raw_arg_begin(), raw_arg_end()); - } + child_range children() { return child_range(raw_arg_begin(), raw_arg_end()); } }; /// Represents a \c delete expression for memory deallocation and @@ -2562,58 +2633,54 @@ public: /// A reference to an overloaded function set, either an /// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr. class OverloadExpr : public Expr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + /// The common name of these declarations. DeclarationNameInfo NameInfo; /// 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 = nullptr; - - unsigned NumResults = 0; - protected: - /// Whether the name includes info for explicit template - /// keyword and arguments. - bool HasTemplateKWAndArgsInfo = false; - - OverloadExpr(StmtClass K, const ASTContext &C, + OverloadExpr(StmtClass SC, const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent, - bool KnownInstantiationDependent, + bool KnownDependent, bool KnownInstantiationDependent, bool KnownContainsUnexpandedParameterPack); - OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty) {} + OverloadExpr(StmtClass SC, EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo); - /// Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo * - getTrailingASTTemplateKWAndArgsInfo(); // defined far below. + /// Return the results. Defined after UnresolvedMemberExpr. + inline DeclAccessPair *getTrailingResults(); + const DeclAccessPair *getTrailingResults() const { + return const_cast<OverloadExpr *>(this)->getTrailingResults(); + } /// Return the optional template keyword and arguments info. + /// Defined after UnresolvedMemberExpr. + inline ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo(); const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const { return const_cast<OverloadExpr *>(this) ->getTrailingASTTemplateKWAndArgsInfo(); } - /// Return the optional template arguments. - TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below + /// Return the optional template arguments. Defined after + /// UnresolvedMemberExpr. + inline TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); + const TemplateArgumentLoc *getTrailingTemplateArgumentLoc() const { + return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc(); + } - void initializeResults(const ASTContext &C, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End); + bool hasTemplateKWAndArgsInfo() const { + return OverloadExprBits.HasTemplateKWAndArgsInfo; + } public: - friend class ASTStmtReader; - friend class ASTStmtWriter; - struct FindResult { OverloadExpr *Expression; bool IsAddressOfOperand; @@ -2649,20 +2716,26 @@ public: } /// Gets the naming class of this lookup, if any. - CXXRecordDecl *getNamingClass() const; + /// Defined after UnresolvedMemberExpr. + inline CXXRecordDecl *getNamingClass(); + const CXXRecordDecl *getNamingClass() const { + return const_cast<OverloadExpr *>(this)->getNamingClass(); + } using decls_iterator = UnresolvedSetImpl::iterator; - decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); } + decls_iterator decls_begin() const { + return UnresolvedSetIterator(getTrailingResults()); + } decls_iterator decls_end() const { - return UnresolvedSetIterator(Results + NumResults); + return UnresolvedSetIterator(getTrailingResults() + getNumDecls()); } llvm::iterator_range<decls_iterator> decls() const { return llvm::make_range(decls_begin(), decls_end()); } /// Gets the number of declarations in the unresolved set. - unsigned getNumDecls() const { return NumResults; } + unsigned getNumDecls() const { return OverloadExprBits.NumResults; } /// Gets the full name info. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } @@ -2685,21 +2758,24 @@ public: /// Retrieve the location of the template keyword preceding /// this name, if any. SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc; } /// 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(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc; } /// 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(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc; } @@ -2751,86 +2827,82 @@ public: /// members and therefore appear only in UnresolvedMemberLookupExprs. class UnresolvedLookupExpr final : public OverloadExpr, - private llvm::TrailingObjects< - UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + private llvm::TrailingObjects<UnresolvedLookupExpr, DeclAccessPair, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { friend class ASTStmtReader; friend class OverloadExpr; friend TrailingObjects; - /// True if these lookup results should be extended by - /// argument-dependent lookup if this is the operand of a function - /// call. - bool RequiresADL = false; - - /// True if these lookup results are overloaded. This is pretty - /// trivially rederivable if we urgently need to kill this field. - bool Overloaded = false; - /// 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 = nullptr; - - UnresolvedLookupExpr(const ASTContext &C, - CXXRecordDecl *NamingClass, + /// but that can be fairly expensive for unqualified lookups. + CXXRecordDecl *NamingClass; + + // UnresolvedLookupExpr is followed by several trailing objects. + // They are in order: + // + // * An array of getNumResults() DeclAccessPair for the results. These are + // undesugared, which is to say, they may include UsingShadowDecls. + // Access is relative to the naming class. + // + // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified + // template keyword and arguments. Present if and only if + // hasTemplateKWAndArgsInfo(). + // + // * An array of getNumTemplateArgs() TemplateArgumentLoc containing + // location information for the explicitly specified template arguments. + + UnresolvedLookupExpr(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - bool RequiresADL, bool Overloaded, + 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) {} + UnresolvedSetIterator Begin, UnresolvedSetIterator End); - UnresolvedLookupExpr(EmptyShell Empty) - : OverloadExpr(UnresolvedLookupExprClass, Empty) {} + UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo); - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; + unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const { + return getNumDecls(); + } + + unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); } 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, + static UnresolvedLookupExpr * + Create(const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); + + static UnresolvedLookupExpr * + Create(const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, + const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, + UnresolvedSetIterator End); + + static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, + unsigned NumResults, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); /// True if this declaration should be extended by /// argument-dependent lookup. - bool requiresADL() const { return RequiresADL; } + bool requiresADL() const { return UnresolvedLookupExprBits.RequiresADL; } /// True if this lookup is overloaded. - bool isOverloaded() const { return Overloaded; } + bool isOverloaded() const { return UnresolvedLookupExprBits.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; } + CXXRecordDecl *getNamingClass() { return NamingClass; } + const CXXRecordDecl *getNamingClass() const { return NamingClass; } SourceLocation getBeginLoc() const LLVM_READONLY { if (NestedNameSpecifierLoc l = getQualifierLoc()) @@ -2872,6 +2944,10 @@ class DependentScopeDeclRefExpr final private llvm::TrailingObjects<DependentScopeDeclRefExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// The nested-name-specifier that qualifies this unresolved /// declaration name. NestedNameSpecifierLoc QualifierLoc; @@ -2879,32 +2955,26 @@ class DependentScopeDeclRefExpr final /// The name of the entity we will be referencing. DeclarationNameInfo NameInfo; - /// Whether the name includes info for explicit template - /// keyword and arguments. - bool HasTemplateKWAndArgsInfo; - - DependentScopeDeclRefExpr(QualType T, - NestedNameSpecifierLoc QualifierLoc, + DependentScopeDeclRefExpr(QualType Ty, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args); size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; + return hasTemplateKWAndArgsInfo(); } -public: - friend class ASTStmtReader; - friend class ASTStmtWriter; - friend TrailingObjects; + bool hasTemplateKWAndArgsInfo() const { + return DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo; + } - static DependentScopeDeclRefExpr *Create(const ASTContext &C, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs); +public: + static DependentScopeDeclRefExpr * + Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs); - static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &C, + static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &Context, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); @@ -2932,21 +3002,24 @@ public: /// Retrieve the location of the template keyword preceding /// this name, if any. SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// 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(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// 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(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } @@ -3100,7 +3173,7 @@ class CXXUnresolvedConstructExpr final friend TrailingObjects; /// The type being constructed. - TypeSourceInfo *Type = nullptr; + TypeSourceInfo *TSI; /// The location of the left parentheses ('('). SourceLocation LParenLoc; @@ -3108,34 +3181,31 @@ class CXXUnresolvedConstructExpr final /// The location of the right parentheses (')'). SourceLocation RParenLoc; - /// The number of arguments used to construct the type. - unsigned NumArgs; - - CXXUnresolvedConstructExpr(TypeSourceInfo *Type, - SourceLocation LParenLoc, - ArrayRef<Expr*> Args, - SourceLocation RParenLoc); + CXXUnresolvedConstructExpr(TypeSourceInfo *TSI, SourceLocation LParenLoc, + ArrayRef<Expr *> Args, SourceLocation RParenLoc); CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) {} + : Expr(CXXUnresolvedConstructExprClass, Empty) { + CXXUnresolvedConstructExprBits.NumArgs = NumArgs; + } public: - static CXXUnresolvedConstructExpr *Create(const ASTContext &C, + static CXXUnresolvedConstructExpr *Create(const ASTContext &Context, TypeSourceInfo *Type, SourceLocation LParenLoc, - ArrayRef<Expr*> Args, + ArrayRef<Expr *> Args, SourceLocation RParenLoc); - static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &C, + static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &Context, unsigned NumArgs); /// Retrieve the type that is being constructed, as specified /// in the source code. - QualType getTypeAsWritten() const { return Type->getType(); } + QualType getTypeAsWritten() const { return TSI->getType(); } /// Retrieve the type source information for the type being /// constructed. - TypeSourceInfo *getTypeSourceInfo() const { return Type; } + TypeSourceInfo *getTypeSourceInfo() const { return TSI; } /// Retrieve the location of the left parentheses ('(') that /// precedes the argument list. @@ -3153,46 +3223,43 @@ public: bool isListInitialization() const { return LParenLoc.isInvalid(); } /// Retrieve the number of arguments. - unsigned arg_size() const { return NumArgs; } + unsigned arg_size() const { return CXXUnresolvedConstructExprBits.NumArgs; } using arg_iterator = Expr **; using arg_range = llvm::iterator_range<arg_iterator>; arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); } - arg_iterator arg_end() { return arg_begin() + NumArgs; } + arg_iterator arg_end() { return arg_begin() + arg_size(); } arg_range arguments() { return arg_range(arg_begin(), arg_end()); } using const_arg_iterator = const Expr* const *; using const_arg_range = llvm::iterator_range<const_arg_iterator>; const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); } - const_arg_iterator arg_end() const { - return arg_begin() + NumArgs; - } + const_arg_iterator arg_end() const { return arg_begin() + arg_size(); } const_arg_range arguments() const { return const_arg_range(arg_begin(), arg_end()); } Expr *getArg(unsigned I) { - assert(I < NumArgs && "Argument index out-of-range"); - return *(arg_begin() + I); + assert(I < arg_size() && "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); + assert(I < arg_size() && "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; + assert(I < arg_size() && "Argument index out-of-range"); + arg_begin()[I] = E; } SourceLocation getBeginLoc() const LLVM_READONLY; - SourceLocation getEndLoc() const LLVM_READONLY { - if (!RParenLoc.isValid() && NumArgs > 0) - return getArg(NumArgs - 1)->getEndLoc(); + if (!RParenLoc.isValid() && arg_size() > 0) + return getArg(arg_size() - 1)->getEndLoc(); return RParenLoc; } @@ -3203,7 +3270,7 @@ public: // Iterators child_range children() { auto **begin = reinterpret_cast<Stmt **>(arg_begin()); - return child_range(begin, begin + NumArgs); + return child_range(begin, begin + arg_size()); } }; @@ -3218,7 +3285,11 @@ class CXXDependentScopeMemberExpr final : public Expr, private llvm::TrailingObjects<CXXDependentScopeMemberExpr, ASTTemplateKWAndArgsInfo, - TemplateArgumentLoc> { + TemplateArgumentLoc, NamedDecl *> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// 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; @@ -3227,40 +3298,53 @@ class CXXDependentScopeMemberExpr final /// implicit accesses. QualType BaseType; - /// Whether this member expression used the '->' operator or - /// the '.' operator. - bool IsArrow : 1; - - /// Whether this member expression has info for explicit template - /// keyword and arguments. - bool HasTemplateKWAndArgsInfo : 1; - - /// The location of the '->' or '.' operator. - SourceLocation OperatorLoc; - /// The nested-name-specifier that precedes the member name, if any. + /// FIXME: This could be in principle store as a trailing object. + /// However the performance impact of doing so should be investigated first. NestedNameSpecifierLoc QualifierLoc; - /// 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; - /// 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 is followed by several trailing objects, + // some of which optional. They are in order: + // + // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified + // template keyword and arguments. Present if and only if + // hasTemplateKWAndArgsInfo(). + // + // * An array of getNumTemplateArgs() TemplateArgumentLoc containing location + // information for the explicitly specified template arguments. + // + // * An optional NamedDecl *. 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. Present if and only if hasFirstQualifierFoundInScope(). + + bool hasTemplateKWAndArgsInfo() const { + return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo; + } + + bool hasFirstQualifierFoundInScope() const { + return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope; + } + + unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); } - CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, + unsigned numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const { + return getNumTemplateArgs(); + } + + unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const { + return hasFirstQualifierFoundInScope(); + } + + CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, @@ -3269,33 +3353,29 @@ class CXXDependentScopeMemberExpr final DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); -public: - friend class ASTStmtReader; - friend class ASTStmtWriter; - friend TrailingObjects; - - CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, - QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo); + CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasTemplateKWAndArgsInfo, + bool HasFirstQualifierFoundInScope); +public: static CXXDependentScopeMemberExpr * - Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, + Create(const ASTContext &Ctx, 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); + CreateEmpty(const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope); /// 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; + bool isImplicitAccess() const { + if (!Base) + return true; + return cast<Expr>(Base)->isImplicitCXXThis(); + } /// Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -3308,13 +3388,14 @@ public: /// Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. - bool isArrow() const { return IsArrow; } + bool isArrow() const { return CXXDependentScopeMemberExprBits.IsArrow; } /// Retrieve the location of the '->' or '.' operator. - SourceLocation getOperatorLoc() const { return OperatorLoc; } + SourceLocation getOperatorLoc() const { + return CXXDependentScopeMemberExprBits.OperatorLoc; + } - /// Retrieve the nested-name-specifier that qualifies the member - /// name. + /// Retrieve the nested-name-specifier that qualifies the member name. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3335,17 +3416,17 @@ public: /// 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; + if (!hasFirstQualifierFoundInScope()) + return nullptr; + return *getTrailingObjects<NamedDecl *>(); } - /// Retrieve the name of the member that this expression - /// refers to. + /// Retrieve the name of the member that this expression refers to. const DeclarationNameInfo &getMemberNameInfo() const { return MemberNameInfo; } - /// Retrieve the name of the member that this expression - /// refers to. + /// Retrieve the name of the member that this expression refers to. DeclarationName getMember() const { return MemberNameInfo.getName(); } // Retrieve the location of the name of the member that this @@ -3355,21 +3436,24 @@ public: /// Retrieve the location of the template keyword preceding the /// member name, if any. SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// 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(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// 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(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } @@ -3453,25 +3537,18 @@ public: /// DeclRefExpr, depending on whether the member is static. class UnresolvedMemberExpr final : public OverloadExpr, - private llvm::TrailingObjects< - UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + private llvm::TrailingObjects<UnresolvedMemberExpr, DeclAccessPair, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { friend class ASTStmtReader; friend class OverloadExpr; friend TrailingObjects; - /// Whether this member expression used the '->' operator or - /// the '.' operator. - bool IsArrow : 1; - - /// Whether the lookup results contain an unresolved using - /// declaration. - bool HasUnresolvedUsing : 1; - /// 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 = nullptr; + Stmt *Base; /// The type of the base expression; never null. QualType BaseType; @@ -3479,7 +3556,21 @@ class UnresolvedMemberExpr final /// The location of the '->' or '.' operator. SourceLocation OperatorLoc; - UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing, + // UnresolvedMemberExpr is followed by several trailing objects. + // They are in order: + // + // * An array of getNumResults() DeclAccessPair for the results. These are + // undesugared, which is to say, they may include UsingShadowDecls. + // Access is relative to the naming class. + // + // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified + // template keyword and arguments. Present if and only if + // hasTemplateKWAndArgsInfo(). + // + // * An array of getNumTemplateArgs() TemplateArgumentLoc containing + // location information for the explicitly specified template arguments. + + UnresolvedMemberExpr(const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, @@ -3488,28 +3579,30 @@ class UnresolvedMemberExpr final const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); - UnresolvedMemberExpr(EmptyShell Empty) - : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), - HasUnresolvedUsing(false) {} + UnresolvedMemberExpr(EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo); - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; + unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const { + return getNumDecls(); + } + + unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); } public: static UnresolvedMemberExpr * - Create(const ASTContext &C, bool HasUnresolvedUsing, - Expr *Base, QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, + Create(const ASTContext &Context, 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); + static UnresolvedMemberExpr *CreateEmpty(const ASTContext &Context, + unsigned NumResults, + bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs); /// True if this is an implicit access, i.e., one in which the /// member being accessed was not written in the source. @@ -3532,32 +3625,36 @@ public: /// Determine whether the lookup results contain an unresolved using /// declaration. - bool hasUnresolvedUsing() const { return HasUnresolvedUsing; } + bool hasUnresolvedUsing() const { + return UnresolvedMemberExprBits.HasUnresolvedUsing; + } /// Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. - bool isArrow() const { return IsArrow; } + bool isArrow() const { return UnresolvedMemberExprBits.IsArrow; } /// Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } /// Retrieve the naming class of this lookup. - CXXRecordDecl *getNamingClass() const; + CXXRecordDecl *getNamingClass(); + const CXXRecordDecl *getNamingClass() const { + return const_cast<UnresolvedMemberExpr *>(this)->getNamingClass(); + } /// Retrieve the full name info for the member that this expression /// refers to. const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); } - /// Retrieve the name of the member that this expression - /// refers to. + /// Retrieve the name of the member that this expression refers to. DeclarationName getMemberName() const { return getName(); } - // Retrieve the location of the name of the member that this - // expression refers to. + /// Retrieve the location of the name of the member that this + /// expression refers to. SourceLocation getMemberLoc() const { return getNameLoc(); } - // Return the preferred location (the member name) for the arrow when - // diagnosing a problem with this expression. + /// 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 getBeginLoc() const LLVM_READONLY { @@ -3586,26 +3683,33 @@ public: } }; -inline ASTTemplateKWAndArgsInfo * -OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) +DeclAccessPair *OverloadExpr::getTrailingResults() { + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getTrailingObjects<DeclAccessPair>(); + return cast<UnresolvedMemberExpr>(this)->getTrailingObjects<DeclAccessPair>(); +} + +ASTTemplateKWAndArgsInfo *OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() { + if (!hasTemplateKWAndArgsInfo()) return nullptr; - if (isa<UnresolvedLookupExpr>(this)) - return cast<UnresolvedLookupExpr>(this) - ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); - else - return cast<UnresolvedMemberExpr>(this) - ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); + 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>(); +TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getTrailingObjects<TemplateArgumentLoc>(); + return cast<UnresolvedMemberExpr>(this) + ->getTrailingObjects<TemplateArgumentLoc>(); +} + +CXXRecordDecl *OverloadExpr::getNamingClass() { + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getNamingClass(); + return cast<UnresolvedMemberExpr>(this)->getNamingClass(); } /// Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]). @@ -3615,7 +3719,6 @@ inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { class CXXNoexceptExpr : public Expr { friend class ASTStmtReader; - bool Value : 1; Stmt *Operand; SourceRange Range; @@ -3623,21 +3726,23 @@ 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, + /*TypeDependent*/ false, + /*ValueDependent*/ Val == CT_Dependent, Val == CT_Dependent || Operand->isInstantiationDependent(), Operand->containsUnexpandedParameterPack()), - Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen) {} + Operand(Operand), Range(Keyword, RParen) { + CXXNoexceptExprBits.Value = Val == CT_Cannot; + } CXXNoexceptExpr(EmptyShell Empty) : Expr(CXXNoexceptExprClass, Empty) {} - Expr *getOperand() const { return static_cast<Expr*>(Operand); } + Expr *getOperand() const { return static_cast<Expr *>(Operand); } - SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } + SourceRange getSourceRange() const { return Range; } - bool getValue() const { return Value; } + bool getValue() const { return CXXNoexceptExprBits.Value; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNoexceptExprClass; @@ -3860,27 +3965,27 @@ class SubstNonTypeTemplateParmExpr : public Expr { /// The replacement expression. Stmt *Replacement; - /// The location of the non-type template parameter reference. - SourceLocation NameLoc; - 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 getBeginLoc() const LLVM_READONLY { return NameLoc; } - SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; } + SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind, + SourceLocation Loc, + NonTypeTemplateParmDecl *Param, + Expr *Replacement) + : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary, + Replacement->isTypeDependent(), Replacement->isValueDependent(), + Replacement->isInstantiationDependent(), + Replacement->containsUnexpandedParameterPack()), + Param(Param), Replacement(Replacement) { + SubstNonTypeTemplateParmExprBits.NameLoc = Loc; + } + + SourceLocation getNameLoc() const { + return SubstNonTypeTemplateParmExprBits.NameLoc; + } + SourceLocation getBeginLoc() const { return getNameLoc(); } + SourceLocation getEndLoc() const { return getNameLoc(); } Expr *getReplacement() const { return cast<Expr>(Replacement); } @@ -3891,7 +3996,7 @@ public: } // Iterators - child_range children() { return child_range(&Replacement, &Replacement+1); } + child_range children() { return child_range(&Replacement, &Replacement + 1); } }; /// Represents a reference to a non-type template parameter pack that diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index ed3d3840b3..c7b305f330 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -1574,8 +1574,7 @@ public: /// \endcode class ObjCBridgedCastExpr final : public ExplicitCastExpr, - private llvm::TrailingObjects< - ObjCBridgedCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> { + private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> { friend class ASTStmtReader; friend class ASTStmtWriter; friend class CastExpr; @@ -1585,10 +1584,6 @@ class ObjCBridgedCastExpr final SourceLocation BridgeKeywordLoc; unsigned Kind : 2; - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind, CastKind CK, SourceLocation BridgeKeywordLoc, diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index c42fe91b32..309ed5a1a5 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_MANGLE_H #define LLVM_CLANG_AST_MANGLE_H +#include "clang/AST/Decl.h" #include "clang/AST/Type.h" #include "clang/Basic/ABI.h" #include "llvm/ADT/DenseMap.h" diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index e93f7e2b3e..bdcdf74b26 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -4061,8 +4061,19 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, return getUniqueDeclarationsNum() + getTotalComponentListNum(); } - /// Map type modifier for the 'map' clause. - OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; +public: + /// Number of allowed map-type-modifiers. + static constexpr unsigned NumberOfModifiers = + OMPC_MAP_MODIFIER_last - OMPC_MAP_MODIFIER_unknown - 1; + +private: + /// Map-type-modifiers for the 'map' clause. + OpenMPMapModifierKind MapTypeModifiers[NumberOfModifiers] = { + OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown + }; + + /// Location of map-type-modifiers for the 'map' clause. + SourceLocation MapTypeModifiersLoc[NumberOfModifiers]; /// Map type for the 'map' clause. OpenMPMapClauseKind MapType = OMPC_MAP_unknown; @@ -4080,7 +4091,8 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, /// NumUniqueDeclarations declarations, \a NumComponentLists total component /// lists, and \a NumComponents total expression components. /// - /// \param MapTypeModifier Map type modifier. + /// \param MapModifiers Map-type-modifiers. + /// \param MapModifiersLoc Locations of map-type-modifiers. /// \param MapType Map type. /// \param MapTypeIsImplicit Map type is inferred implicitly. /// \param MapLoc Location of the map type. @@ -4091,7 +4103,8 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier, + explicit OMPMapClause(ArrayRef<OpenMPMapModifierKind> MapModifiers, + ArrayRef<SourceLocation> MapModifiersLoc, OpenMPMapClauseKind MapType, bool MapTypeIsImplicit, SourceLocation MapLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, @@ -4100,8 +4113,17 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, : OMPMappableExprListClause(OMPC_map, StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents), - MapTypeModifier(MapTypeModifier), MapType(MapType), - MapTypeIsImplicit(MapTypeIsImplicit), MapLoc(MapLoc) {} + MapType(MapType), MapTypeIsImplicit(MapTypeIsImplicit), + MapLoc(MapLoc) { + assert(llvm::array_lengthof(MapTypeModifiers) == MapModifiers.size() + && "Unexpected number of map type modifiers."); + llvm::copy(MapModifiers, std::begin(MapTypeModifiers)); + + assert(llvm::array_lengthof(MapTypeModifiersLoc) == + MapModifiersLoc.size() && + "Unexpected number of map type modifier locations."); + llvm::copy(MapModifiersLoc, std::begin(MapTypeModifiersLoc)); + } /// Build an empty clause. /// @@ -4116,10 +4138,25 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, OMPC_map, SourceLocation(), SourceLocation(), SourceLocation(), NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {} - /// Set type modifier for the clause. + /// Set map-type-modifier for the clause. /// - /// \param T Type Modifier for the clause. - void setMapTypeModifier(OpenMPMapClauseKind T) { MapTypeModifier = T; } + /// \param I index for map-type-modifier. + /// \param T map-type-modifier for the clause. + void setMapTypeModifier(unsigned I, OpenMPMapModifierKind T) { + assert(I < NumberOfModifiers && + "Unexpected index to store map type modifier, exceeds array size."); + MapTypeModifiers[I] = T; + } + + /// Set location for the map-type-modifier. + /// + /// \param I index for map-type-modifier location. + /// \param TLoc map-type-modifier location. + void setMapTypeModifierLoc(unsigned I, SourceLocation TLoc) { + assert(I < NumberOfModifiers && + "Index to store map type modifier location exceeds array size."); + MapTypeModifiersLoc[I] = TLoc; + } /// Set type for the clause. /// @@ -4143,7 +4180,8 @@ public: /// \param Vars The original expression used in the clause. /// \param Declarations Declarations used in the clause. /// \param ComponentLists Component lists used in the clause. - /// \param TypeModifier Map type modifier. + /// \param MapModifiers Map-type-modifiers. + /// \param MapModifiersLoc Location of map-type-modifiers. /// \param Type Map type. /// \param TypeIsImplicit Map type is inferred implicitly. /// \param TypeLoc Location of the map type. @@ -4152,7 +4190,8 @@ public: ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, MappableExprComponentListsRef ComponentLists, - OpenMPMapClauseKind TypeModifier, + ArrayRef<OpenMPMapModifierKind> MapModifiers, + ArrayRef<SourceLocation> MapModifiersLoc, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc); @@ -4182,9 +4221,33 @@ public: /// messages for some target directives. bool isImplicitMapType() const LLVM_READONLY { return MapTypeIsImplicit; } - /// Fetches the map type modifier for the clause. - OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY { - return MapTypeModifier; + /// Fetches the map-type-modifier at 'Cnt' index of array of modifiers. + /// + /// \param Cnt index for map-type-modifier. + OpenMPMapModifierKind getMapTypeModifier(unsigned Cnt) const LLVM_READONLY { + assert(Cnt < NumberOfModifiers && + "Requested modifier exceeds the total number of modifiers."); + return MapTypeModifiers[Cnt]; + } + + /// Fetches the map-type-modifier location at 'Cnt' index of array of + /// modifiers' locations. + /// + /// \param Cnt index for map-type-modifier location. + SourceLocation getMapTypeModifierLoc(unsigned Cnt) const LLVM_READONLY { + assert(Cnt < NumberOfModifiers && + "Requested modifier location exceeds total number of modifiers."); + return MapTypeModifiersLoc[Cnt]; + } + + /// Fetches ArrayRef of map-type-modifiers. + ArrayRef<OpenMPMapModifierKind> getMapTypeModifiers() const LLVM_READONLY { + return llvm::makeArrayRef(MapTypeModifiers); + } + + /// Fetches ArrayRef of location of map-type-modifiers. + ArrayRef<SourceLocation> getMapTypeModifiersLoc() const LLVM_READONLY { + return llvm::makeArrayRef(MapTypeModifiersLoc); } /// Fetches location of clause mapping kind. diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 0a4dc42898..3c877f5ea1 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -51,7 +51,7 @@ struct PrintingPolicy { MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false), ConstantsAsWritten(false), SuppressImplicitBase(false), FullyQualifiedName(false), - RemapFilePaths(false) {} + RemapFilePaths(false), PrintCanonicalTypes(false) {} /// Adjust this printing policy for cases where it's known that we're /// printing C++ code (for instance, if AST dumping reaches a C++-only @@ -228,6 +228,9 @@ struct PrintingPolicy { /// Whether to apply -fdebug-prefix-map to any file paths. unsigned RemapFilePaths : 1; + /// Whether to print types as written or canonically. + unsigned PrintCanonicalTypes : 1; + /// When RemapFilePaths is true, this function performs the action. std::function<std::string(StringRef)> remapPath; }; diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index eb582c7a7a..44aba63557 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -298,14 +298,6 @@ public: bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, Expr *Init); - /// 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); - /// Recursively visit the syntactic or semantic form of an /// initialization list. /// @@ -936,13 +928,6 @@ RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE, 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. @@ -1383,9 +1368,14 @@ DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) template <typename Derived> bool RecursiveASTVisitor<Derived>::canIgnoreChildDeclWhileTraversingDeclContext( const Decl *Child) { - // BlockDecls and CapturedDecls are traversed through BlockExprs and - // CapturedStmts respectively. - return isa<BlockDecl>(Child) || isa<CapturedDecl>(Child); + // BlockDecls are traversed through BlockExprs, + // CapturedDecls are traversed through CapturedStmts. + if (isa<BlockDecl>(Child) || isa<CapturedDecl>(Child)) + return true; + // Lambda classes are traversed through LambdaExprs. + if (const CXXRecordDecl* Cls = dyn_cast<CXXRecordDecl>(Child)) + return Cls->isLambda(); + return false; } template <typename Derived> @@ -2404,6 +2394,7 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { // Walk only the visible parts of lambda expressions. DEF_TRAVERSE_STMT(LambdaExpr, { + // Visit the capture list. for (unsigned I = 0, N = S->capture_size(); I != N; ++I) { const LambdaCapture *C = S->capture_begin() + I; if (C->isExplicit() || getDerived().shouldVisitImplicitCode()) { @@ -2411,32 +2402,31 @@ DEF_TRAVERSE_STMT(LambdaExpr, { } } - TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); - FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>(); - - if (S->hasExplicitParameters() && S->hasExplicitResultType()) { - // Visit the whole type. - TRY_TO(TraverseTypeLoc(TL)); + if (getDerived().shouldVisitImplicitCode()) { + // The implicit model is simple: everything else is in the lambda class. + TRY_TO(TraverseDecl(S->getLambdaClass())); } else { + // We need to poke around to find the bits that might be explicitly written. + TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); + FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>(); + if (S->hasExplicitParameters()) { // Visit parameters. - for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { + 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())); } + if (S->hasExplicitResultType()) + TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); auto *T = Proto.getTypePtr(); - for (const auto &E : T->exceptions()) { + for (const auto &E : T->exceptions()) TRY_TO(TraverseType(E)); - } if (Expr *NE = T->getNoexceptExpr()) TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE); - } - ReturnValue = TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); + } ShouldVisitChildren = false; }) diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 23ac5af7ae..ff5baa21ad 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -433,7 +433,16 @@ protected: /// True if the callee of the call expression was found using ADL. unsigned UsesADL : 1; + + /// Padding used to align OffsetToTrailingObjects to a byte multiple. + unsigned : 24 - 2 - NumExprBits; + + /// The offset in bytes from the this pointer to the start of the + /// trailing objects belonging to CallExpr. Intentionally byte sized + /// for faster access. + unsigned OffsetToTrailingObjects : 8; }; + enum { NumCallExprBits = 32 }; class MemberExprBitfields { friend class MemberExpr; @@ -472,7 +481,10 @@ protected: unsigned Kind : 6; unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr. - unsigned BasePathIsEmpty : 1; + + /// The number of CXXBaseSpecifiers in the cast. 14 bits would be enough + /// here. ([implimits] Direct and indirect base classes [16384]). + unsigned BasePathSize; }; class BinaryOperatorBitfields { @@ -523,6 +535,20 @@ protected: //===--- C++ Expression bitfields classes ---===// + class CXXOperatorCallExprBitfields { + friend class ASTStmtReader; + friend class CXXOperatorCallExpr; + + unsigned : NumCallExprBits; + + /// The kind of this overloaded operator. One of the enumerator + /// value of OverloadedOperatorKind. + unsigned OperatorKind : 6; + + // Only meaningful for floating point types. + unsigned FPFeatures : 3; + }; + class CXXBoolLiteralExprBitfields { friend class CXXBoolLiteralExpr; @@ -589,6 +615,48 @@ protected: SourceLocation Loc; }; + class CXXScalarValueInitExprBitfields { + friend class ASTStmtReader; + friend class CXXScalarValueInitExpr; + + unsigned : NumExprBits; + + SourceLocation RParenLoc; + }; + + class CXXNewExprBitfields { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend class CXXNewExpr; + + unsigned : NumExprBits; + + /// Was the usage ::new, i.e. is the global new to be used? + unsigned IsGlobalNew : 1; + + /// Do we allocate an array? If so, the first trailing "Stmt *" is the + /// size expression. + unsigned IsArray : 1; + + /// Should the alignment be passed to the allocation function? + unsigned ShouldPassAlignment : 1; + + /// If this is an array allocation, does the usual deallocation + /// function for the allocated type want to know the allocated size? + unsigned UsualArrayDeleteWantsSize : 1; + + /// 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; + + /// True if the allocated type was expressed as a parenthesized type-id. + unsigned IsParenTypeId : 1; + + /// The number of placement new arguments. + unsigned NumPlacementArgs; + }; + class CXXDeleteExprBitfields { friend class ASTStmtReader; friend class CXXDeleteExpr; @@ -632,6 +700,34 @@ protected: unsigned NumArgs : 32 - 8 - 1 - NumExprBits; }; + class DependentScopeDeclRefExprBitfields { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend class DependentScopeDeclRefExpr; + + unsigned : NumExprBits; + + /// Whether the name includes info for explicit template + /// keyword and arguments. + unsigned HasTemplateKWAndArgsInfo : 1; + }; + + class CXXConstructExprBitfields { + friend class ASTStmtReader; + friend class CXXConstructExpr; + + unsigned : NumExprBits; + + unsigned Elidable : 1; + unsigned HadMultipleCandidates : 1; + unsigned ListInitialization : 1; + unsigned StdInitListInitialization : 1; + unsigned ZeroInitialization : 1; + unsigned ConstructionKind : 3; + + SourceLocation Loc; + }; + class ExprWithCleanupsBitfields { friend class ASTStmtReader; // deserialization friend class ExprWithCleanups; @@ -644,6 +740,112 @@ protected: unsigned NumObjects : 32 - 1 - NumExprBits; }; + class CXXUnresolvedConstructExprBitfields { + friend class ASTStmtReader; + friend class CXXUnresolvedConstructExpr; + + unsigned : NumExprBits; + + /// The number of arguments used to construct the type. + unsigned NumArgs; + }; + + class CXXDependentScopeMemberExprBitfields { + friend class ASTStmtReader; + friend class CXXDependentScopeMemberExpr; + + unsigned : NumExprBits; + + /// Whether this member expression used the '->' operator or + /// the '.' operator. + unsigned IsArrow : 1; + + /// Whether this member expression has info for explicit template + /// keyword and arguments. + unsigned HasTemplateKWAndArgsInfo : 1; + + /// See getFirstQualifierFoundInScope() and the comment listing + /// the trailing objects. + unsigned HasFirstQualifierFoundInScope : 1; + + /// The location of the '->' or '.' operator. + SourceLocation OperatorLoc; + }; + + class OverloadExprBitfields { + friend class ASTStmtReader; + friend class OverloadExpr; + + unsigned : NumExprBits; + + /// Whether the name includes info for explicit template + /// keyword and arguments. + unsigned HasTemplateKWAndArgsInfo : 1; + + /// Padding used by the derived classes to store various bits. If you + /// need to add some data here, shrink this padding and add your data + /// above. NumOverloadExprBits also needs to be updated. + unsigned : 32 - NumExprBits - 1; + + /// The number of results. + unsigned NumResults; + }; + enum { NumOverloadExprBits = NumExprBits + 1 }; + + class UnresolvedLookupExprBitfields { + friend class ASTStmtReader; + friend class UnresolvedLookupExpr; + + unsigned : NumOverloadExprBits; + + /// True if these lookup results should be extended by + /// argument-dependent lookup if this is the operand of a function call. + unsigned RequiresADL : 1; + + /// True if these lookup results are overloaded. This is pretty trivially + /// rederivable if we urgently need to kill this field. + unsigned Overloaded : 1; + }; + static_assert(sizeof(UnresolvedLookupExprBitfields) <= 4, + "UnresolvedLookupExprBitfields must be <= than 4 bytes to" + "avoid trashing OverloadExprBitfields::NumResults!"); + + class UnresolvedMemberExprBitfields { + friend class ASTStmtReader; + friend class UnresolvedMemberExpr; + + unsigned : NumOverloadExprBits; + + /// Whether this member expression used the '->' operator or + /// the '.' operator. + unsigned IsArrow : 1; + + /// Whether the lookup results contain an unresolved using declaration. + unsigned HasUnresolvedUsing : 1; + }; + static_assert(sizeof(UnresolvedMemberExprBitfields) <= 4, + "UnresolvedMemberExprBitfields must be <= than 4 bytes to" + "avoid trashing OverloadExprBitfields::NumResults!"); + + class CXXNoexceptExprBitfields { + friend class ASTStmtReader; + friend class CXXNoexceptExpr; + + unsigned : NumExprBits; + + unsigned Value : 1; + }; + + class SubstNonTypeTemplateParmExprBitfields { + friend class ASTStmtReader; + friend class SubstNonTypeTemplateParmExpr; + + unsigned : NumExprBits; + + /// The location of the non-type template parameter reference. + SourceLocation NameLoc; + }; + //===--- C++ Coroutines TS bitfields classes ---===// class CoawaitExprBitfields { @@ -667,13 +869,16 @@ protected: //===--- Clang Extensions bitfields classes ---===// class OpaqueValueExprBitfields { + friend class ASTStmtReader; friend class OpaqueValueExpr; unsigned : NumExprBits; - /// The OVE is a unique semantic reference to its source expressio if this + /// The OVE is a unique semantic reference to its source expression if this /// bit is set to true. unsigned IsUnique : 1; + + SourceLocation Loc; }; union { @@ -714,15 +919,27 @@ protected: PseudoObjectExprBitfields PseudoObjectExprBits; // C++ Expressions + CXXOperatorCallExprBitfields CXXOperatorCallExprBits; CXXBoolLiteralExprBitfields CXXBoolLiteralExprBits; CXXNullPtrLiteralExprBitfields CXXNullPtrLiteralExprBits; CXXThisExprBitfields CXXThisExprBits; CXXThrowExprBitfields CXXThrowExprBits; CXXDefaultArgExprBitfields CXXDefaultArgExprBits; CXXDefaultInitExprBitfields CXXDefaultInitExprBits; + CXXScalarValueInitExprBitfields CXXScalarValueInitExprBits; + CXXNewExprBitfields CXXNewExprBits; CXXDeleteExprBitfields CXXDeleteExprBits; TypeTraitExprBitfields TypeTraitExprBits; + DependentScopeDeclRefExprBitfields DependentScopeDeclRefExprBits; + CXXConstructExprBitfields CXXConstructExprBits; ExprWithCleanupsBitfields ExprWithCleanupsBits; + CXXUnresolvedConstructExprBitfields CXXUnresolvedConstructExprBits; + CXXDependentScopeMemberExprBitfields CXXDependentScopeMemberExprBits; + OverloadExprBitfields OverloadExprBits; + UnresolvedLookupExprBitfields UnresolvedLookupExprBits; + UnresolvedMemberExprBitfields UnresolvedMemberExprBits; + CXXNoexceptExprBitfields CXXNoexceptExprBits; + SubstNonTypeTemplateParmExprBitfields SubstNonTypeTemplateParmExprBits; // C++ Coroutines TS expressions CoawaitExprBitfields CoawaitBits; diff --git a/include/clang/AST/TemplateArgumentVisitor.h b/include/clang/AST/TemplateArgumentVisitor.h new file mode 100644 index 0000000000..e1cc392a17 --- /dev/null +++ b/include/clang/AST/TemplateArgumentVisitor.h @@ -0,0 +1,99 @@ +//===- TemplateArgumentVisitor.h - Visitor for TArg 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 TemplateArgumentVisitor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TEMPLATEARGUMENTVISITOR_H +#define LLVM_CLANG_AST_TEMPLATEARGUMENTVISITOR_H + +#include "clang/AST/TemplateBase.h" + +namespace clang { + +namespace templateargumentvisitor { + +/// A simple visitor class that helps create template argument visitors. +template <template <typename> class Ref, typename ImplClass, + typename RetTy = void, typename... ParamTys> +class Base { +public: +#define REF(CLASS) typename Ref<CLASS>::type +#define DISPATCH(NAME) \ + case TemplateArgument::NAME: \ + return static_cast<ImplClass *>(this)->Visit##NAME##TemplateArgument( \ + TA, std::forward<ParamTys>(P)...) + + RetTy Visit(REF(TemplateArgument) TA, ParamTys... P) { + switch (TA.getKind()) { + DISPATCH(Null); + DISPATCH(Type); + DISPATCH(Declaration); + DISPATCH(NullPtr); + DISPATCH(Integral); + DISPATCH(Template); + DISPATCH(TemplateExpansion); + DISPATCH(Expression); + DISPATCH(Pack); + } + llvm_unreachable("TemplateArgument is not covered in switch!"); + } + + // If the implementation chooses not to implement a certain visit + // method, fall back to the parent. + +#define VISIT_METHOD(CATEGORY) \ + RetTy Visit##CATEGORY##TemplateArgument(REF(TemplateArgument) TA, \ + ParamTys... P) { \ + return VisitTemplateArgument(TA, std::forward<ParamTys>(P)...); \ + } + + VISIT_METHOD(Null); + VISIT_METHOD(Type); + VISIT_METHOD(Declaration); + VISIT_METHOD(NullPtr); + VISIT_METHOD(Integral); + VISIT_METHOD(Template); + VISIT_METHOD(TemplateExpansion); + VISIT_METHOD(Expression); + VISIT_METHOD(Pack); + + RetTy VisitTemplateArgument(REF(TemplateArgument), ParamTys...) { + return RetTy(); + } + +#undef REF +#undef DISPATCH +#undef VISIT_METHOD +}; + +} // namespace templateargumentvisitor + +/// A simple visitor class that helps create template argument visitors. +/// +/// This class does not preserve constness of TemplateArgument references (see +/// also ConstTemplateArgumentVisitor). +template <typename ImplClass, typename RetTy = void, typename... ParamTys> +class TemplateArgumentVisitor + : public templateargumentvisitor::Base<std::add_lvalue_reference, ImplClass, + RetTy, ParamTys...> {}; + +/// A simple visitor class that helps create template argument visitors. +/// +/// This class preserves constness of TemplateArgument references (see also +/// TemplateArgumentVisitor). +template <typename ImplClass, typename RetTy = void, typename... ParamTys> +class ConstTemplateArgumentVisitor + : public templateargumentvisitor::Base<llvm::make_const_ref, ImplClass, + RetTy, ParamTys...> {}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_TEMPLATEARGUMENTVISITOR_H diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 8f92e799d7..e3a773b4e4 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -530,19 +530,22 @@ public: } NestedNameSpecifierLoc getTemplateQualifierLoc() const { - assert(Argument.getKind() == TemplateArgument::Template || - Argument.getKind() == TemplateArgument::TemplateExpansion); + if (Argument.getKind() != TemplateArgument::Template && + Argument.getKind() != TemplateArgument::TemplateExpansion) + return NestedNameSpecifierLoc(); return LocInfo.getTemplateQualifierLoc(); } SourceLocation getTemplateNameLoc() const { - assert(Argument.getKind() == TemplateArgument::Template || - Argument.getKind() == TemplateArgument::TemplateExpansion); + if (Argument.getKind() != TemplateArgument::Template && + Argument.getKind() != TemplateArgument::TemplateExpansion) + return SourceLocation(); return LocInfo.getTemplateNameLoc(); } SourceLocation getTemplateEllipsisLoc() const { - assert(Argument.getKind() == TemplateArgument::TemplateExpansion); + if (Argument.getKind() != TemplateArgument::TemplateExpansion) + return SourceLocation(); return LocInfo.getTemplateEllipsisLoc(); } }; @@ -617,13 +620,17 @@ public: /// The number of template arguments in TemplateArgs. unsigned NumTemplateArgs; + SourceLocation getLAngleLoc() const { return LAngleLoc; } + SourceLocation getRAngleLoc() const { return RAngleLoc; } + /// Retrieve the template arguments const TemplateArgumentLoc *getTemplateArgs() const { return getTrailingObjects<TemplateArgumentLoc>(); } + unsigned getNumTemplateArgs() const { return NumTemplateArgs; } llvm::ArrayRef<TemplateArgumentLoc> arguments() const { - return llvm::makeArrayRef(getTemplateArgs(), NumTemplateArgs); + return llvm::makeArrayRef(getTemplateArgs(), getNumTemplateArgs()); } const TemplateArgumentLoc &operator[](unsigned I) const { diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index d88d58d0a2..48272597d4 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_TEMPLATENAME_H #define LLVM_CLANG_AST_TEMPLATENAME_H +#include "clang/AST/NestedNameSpecifier.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" diff --git a/include/clang/AST/TextNodeDumper.h b/include/clang/AST/TextNodeDumper.h index 5a1dbb40fa..7940663763 100644 --- a/include/clang/AST/TextNodeDumper.h +++ b/include/clang/AST/TextNodeDumper.h @@ -16,15 +16,120 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDumperUtils.h" +#include "clang/AST/AttrVisitor.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TemplateArgumentVisitor.h" +#include "clang/AST/TypeVisitor.h" namespace clang { +class TextTreeStructure { + raw_ostream &OS; + const bool ShowColors; + + /// Pending[i] is an action to dump an entity at level i. + llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending; + + /// Indicates whether we're at the top level. + bool TopLevel = true; + + /// Indicates if we're handling the first child after entering a new depth. + bool FirstChild = true; + + /// Prefix for currently-being-dumped entity. + std::string Prefix; + +public: + /// Add a child of the current node. Calls DoAddChild without arguments + template <typename Fn> void AddChild(Fn DoAddChild) { + return AddChild("", DoAddChild); + } + + /// Add a child of the current node with an optional label. + /// Calls DoAddChild without arguments. + template <typename Fn> void AddChild(StringRef Label, Fn DoAddChild) { + // If we're at the top level, there's nothing interesting to do; just + // run the dumper. + if (TopLevel) { + TopLevel = false; + DoAddChild(); + while (!Pending.empty()) { + Pending.back()(true); + Pending.pop_back(); + } + Prefix.clear(); + OS << "\n"; + TopLevel = true; + return; + } + + // We need to capture an owning-string in the lambda because the lambda + // is invoked in a deferred manner. + std::string LabelStr = Label; + auto DumpWithIndent = [this, DoAddChild, LabelStr](bool IsLastChild) { + // Print out the appropriate tree structure and work out the prefix for + // children of this node. For instance: + // + // A Prefix = "" + // |-B Prefix = "| " + // | `-C Prefix = "| " + // `-D Prefix = " " + // |-E Prefix = " | " + // `-F Prefix = " " + // G Prefix = "" + // + // Note that the first level gets no prefix. + { + OS << '\n'; + ColorScope Color(OS, ShowColors, IndentColor); + OS << Prefix << (IsLastChild ? '`' : '|') << '-'; + if (!LabelStr.empty()) + OS << LabelStr << ": "; + + this->Prefix.push_back(IsLastChild ? ' ' : '|'); + this->Prefix.push_back(' '); + } + + FirstChild = true; + unsigned Depth = Pending.size(); + + DoAddChild(); + + // If any children are left, they're the last at their nesting level. + // Dump those ones out now. + while (Depth < Pending.size()) { + Pending.back()(true); + this->Pending.pop_back(); + } + + // Restore the old prefix. + this->Prefix.resize(Prefix.size() - 2); + }; + + if (FirstChild) { + Pending.push_back(std::move(DumpWithIndent)); + } else { + Pending.back()(false); + Pending.back() = std::move(DumpWithIndent); + } + FirstChild = false; + } + + TextTreeStructure(raw_ostream &OS, bool ShowColors) + : OS(OS), ShowColors(ShowColors) {} +}; + class TextNodeDumper - : public comments::ConstCommentVisitor<TextNodeDumper, void, - const comments::FullComment *> { + : public TextTreeStructure, + public comments::ConstCommentVisitor<TextNodeDumper, void, + const comments::FullComment *>, + public ConstAttrVisitor<TextNodeDumper>, + public ConstTemplateArgumentVisitor<TextNodeDumper>, + public ConstStmtVisitor<TextNodeDumper>, + public TypeVisitor<TextNodeDumper> { raw_ostream &OS; const bool ShowColors; @@ -49,6 +154,25 @@ public: void Visit(const comments::Comment *C, const comments::FullComment *FC); + void Visit(const Attr *A); + + void Visit(const TemplateArgument &TA, SourceRange R, + const Decl *From = nullptr, StringRef Label = {}); + + void Visit(const Stmt *Node); + + void Visit(const Type *T); + + void Visit(QualType T); + + void Visit(const Decl *D); + + void Visit(const CXXCtorInitializer *Init); + + void Visit(const OMPClause *C); + + void Visit(const BlockDecl::Capture &C); + void dumpPointer(const void *Ptr); void dumpLocation(SourceLocation Loc); void dumpSourceRange(SourceRange R); @@ -57,7 +181,8 @@ public: void dumpBareDeclRef(const Decl *D); void dumpName(const NamedDecl *ND); void dumpAccessSpecifier(AccessSpecifier AS); - void dumpCXXTemporary(const CXXTemporary *Temporary); + + void dumpDeclRef(const Decl *D, StringRef Label = {}); void visitTextComment(const comments::TextComment *C, const comments::FullComment *); @@ -80,6 +205,92 @@ public: const comments::FullComment *); void visitVerbatimLineComment(const comments::VerbatimLineComment *C, const comments::FullComment *); + +// Implements Visit methods for Attrs. +#include "clang/AST/AttrTextNodeDump.inc" + + void VisitNullTemplateArgument(const TemplateArgument &TA); + void VisitTypeTemplateArgument(const TemplateArgument &TA); + void VisitDeclarationTemplateArgument(const TemplateArgument &TA); + void VisitNullPtrTemplateArgument(const TemplateArgument &TA); + void VisitIntegralTemplateArgument(const TemplateArgument &TA); + void VisitTemplateTemplateArgument(const TemplateArgument &TA); + void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA); + void VisitExpressionTemplateArgument(const TemplateArgument &TA); + void VisitPackTemplateArgument(const TemplateArgument &TA); + + void VisitIfStmt(const IfStmt *Node); + void VisitSwitchStmt(const SwitchStmt *Node); + void VisitWhileStmt(const WhileStmt *Node); + void VisitLabelStmt(const LabelStmt *Node); + void VisitGotoStmt(const GotoStmt *Node); + void VisitCaseStmt(const CaseStmt *Node); + void VisitCallExpr(const CallExpr *Node); + void VisitCastExpr(const CastExpr *Node); + void VisitImplicitCastExpr(const ImplicitCastExpr *Node); + void VisitDeclRefExpr(const DeclRefExpr *Node); + void VisitPredefinedExpr(const PredefinedExpr *Node); + void VisitCharacterLiteral(const CharacterLiteral *Node); + void VisitIntegerLiteral(const IntegerLiteral *Node); + void VisitFixedPointLiteral(const FixedPointLiteral *Node); + void VisitFloatingLiteral(const FloatingLiteral *Node); + void VisitStringLiteral(const StringLiteral *Str); + void VisitInitListExpr(const InitListExpr *ILE); + void VisitUnaryOperator(const UnaryOperator *Node); + void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node); + void VisitMemberExpr(const MemberExpr *Node); + void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node); + void VisitBinaryOperator(const BinaryOperator *Node); + void VisitCompoundAssignOperator(const CompoundAssignOperator *Node); + void VisitAddrLabelExpr(const AddrLabelExpr *Node); + void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node); + void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node); + void VisitCXXThisExpr(const CXXThisExpr *Node); + void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node); + void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node); + void VisitCXXConstructExpr(const CXXConstructExpr *Node); + void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node); + void VisitCXXNewExpr(const CXXNewExpr *Node); + void VisitCXXDeleteExpr(const CXXDeleteExpr *Node); + void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node); + void VisitExprWithCleanups(const ExprWithCleanups *Node); + void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node); + void VisitSizeOfPackExpr(const SizeOfPackExpr *Node); + void + VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node); + void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node); + void VisitObjCEncodeExpr(const ObjCEncodeExpr *Node); + void VisitObjCMessageExpr(const ObjCMessageExpr *Node); + void VisitObjCBoxedExpr(const ObjCBoxedExpr *Node); + void VisitObjCSelectorExpr(const ObjCSelectorExpr *Node); + void VisitObjCProtocolExpr(const ObjCProtocolExpr *Node); + void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node); + void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node); + void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node); + void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node); + + void VisitRValueReferenceType(const ReferenceType *T); + void VisitArrayType(const ArrayType *T); + void VisitConstantArrayType(const ConstantArrayType *T); + void VisitVariableArrayType(const VariableArrayType *T); + void VisitDependentSizedArrayType(const DependentSizedArrayType *T); + void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T); + void VisitVectorType(const VectorType *T); + void VisitFunctionType(const FunctionType *T); + void VisitFunctionProtoType(const FunctionProtoType *T); + void VisitUnresolvedUsingType(const UnresolvedUsingType *T); + void VisitTypedefType(const TypedefType *T); + void VisitUnaryTransformType(const UnaryTransformType *T); + void VisitTagType(const TagType *T); + void VisitTemplateTypeParmType(const TemplateTypeParmType *T); + void VisitAutoType(const AutoType *T); + void VisitTemplateSpecializationType(const TemplateSpecializationType *T); + void VisitInjectedClassNameType(const InjectedClassNameType *T); + void VisitObjCInterfaceType(const ObjCInterfaceType *T); + void VisitPackExpansionType(const PackExpansionType *T); + +private: + void dumpCXXTemporary(const CXXTemporary *Temporary); }; } // namespace clang diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 5b69570aab..d4c97b1b5e 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -980,9 +980,7 @@ public: void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder = Twine(), - unsigned Indentation = 0) const { - print(split(), OS, Policy, PlaceHolder, Indentation); - } + unsigned Indentation = 0) const; static void print(SplitQualType split, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder, @@ -996,9 +994,7 @@ public: unsigned Indentation = 0); void getAsStringInternal(std::string &Str, - const PrintingPolicy &Policy) const { - return getAsStringInternal(split(), Str, Policy); - } + const PrintingPolicy &Policy) const; static void getAsStringInternal(SplitQualType split, std::string &out, const PrintingPolicy &policy) { @@ -6705,6 +6701,24 @@ inline const Type *Type::getPointeeOrArrayElementType() const { return type; } +/// Insertion operator for diagnostics. This allows sending Qualifiers into a +/// diagnostic with <<. +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + Qualifiers Q) { + DB.AddTaggedVal(Q.getAsOpaqueValue(), + DiagnosticsEngine::ArgumentKind::ak_qual); + return DB; +} + +/// Insertion operator for partial diagnostics. This allows sending Qualifiers +/// into a diagnostic with <<. +inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + Qualifiers Q) { + PD.AddTaggedVal(Q.getAsOpaqueValue(), + DiagnosticsEngine::ArgumentKind::ak_qual); + return PD; +} + /// Insertion operator for diagnostics. This allows sending QualType's into a /// diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |