diff options
Diffstat (limited to 'include')
94 files changed, 3240 insertions, 1620 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, diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index b913e54b37..5cdb964a92 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -1158,6 +1158,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; /// matches 'm'. extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; +/// Matches indirect field declarations. +/// +/// Given +/// \code +/// struct X { struct { int a; }; }; +/// \endcode +/// indirectFieldDecl() +/// matches 'a'. +extern const internal::VariadicDynCastAllOfMatcher<Decl, IndirectFieldDecl> + indirectFieldDecl; + /// Matches function declarations. /// /// Example matches f @@ -3503,6 +3514,19 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument, *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); } +/// Matches the n'th item of an initializer list expression. +/// +/// Example matches y. +/// (matcher = initListExpr(hasInit(0, expr()))) +/// \code +/// int x{y}. +/// \endcode +AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N, + ast_matchers::internal::Matcher<Expr>, InnerMatcher) { + return N < Node.getNumInits() && + InnerMatcher.matches(*Node.getInit(N), Finder, Builder); +} + /// Matches declaration statements that contain a specific number of /// declarations. /// diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 9d9f867d05..34851a907e 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -261,7 +261,7 @@ public: } private: - SmallVector<BoundNodesMap, 16> Bindings; + SmallVector<BoundNodesMap, 1> Bindings; }; class ASTMatchFinder; diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 0cb500fffb..114597661a 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -88,9 +88,13 @@ public: /// before the given block-level expression (see runOnAllBlocks). bool isLive(const Stmt *Loc, const Stmt *StmtVal); - /// Print to stderr the liveness information associated with + /// Print to stderr the variable liveness information associated with /// each basic block. - void dumpBlockLiveness(const SourceManager& M); + void dumpBlockLiveness(const SourceManager &M); + + /// Print to stderr the statement liveness information associated with + /// each basic block. + void dumpStmtLiveness(const SourceManager &M); void runOnAllBlocks(Observer &obs); diff --git a/include/clang/Analysis/ConstructionContext.h b/include/clang/Analysis/ConstructionContext.h index 9c62bac209..27c1d5b9f1 100644 --- a/include/clang/Analysis/ConstructionContext.h +++ b/include/clang/Analysis/ConstructionContext.h @@ -19,6 +19,7 @@ #include "clang/Analysis/Support/BumpVector.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" namespace clang { diff --git a/include/clang/Basic/AlignedAllocation.h b/include/clang/Basic/AlignedAllocation.h index 9751f41184..c995f47a7d 100644 --- a/include/clang/Basic/AlignedAllocation.h +++ b/include/clang/Basic/AlignedAllocation.h @@ -27,8 +27,8 @@ inline llvm::VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) { default: break; case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: // Earliest supporting version is 10.13. - return llvm::VersionTuple(10U, 13U); + case llvm::Triple::MacOSX: // Earliest supporting version is 10.14. + return llvm::VersionTuple(10U, 14U); case llvm::Triple::IOS: case llvm::Triple::TvOS: // Earliest supporting version is 11.0.0. return llvm::VersionTuple(11U); diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 04125e67b2..1fe1dd3994 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -300,6 +300,7 @@ def OpenCL : LangOpt<"OpenCL">; def RenderScript : LangOpt<"RenderScript">; def ObjC : LangOpt<"ObjC">; def BlocksSupported : LangOpt<"Blocks">; +def ObjCAutoRefCount : LangOpt<"ObjCAutoRefCount">; // Defines targets for target-specific attributes. Empty lists are unchecked. class TargetSpec { @@ -840,13 +841,25 @@ def OSConsumed : InheritableParamAttr { def OSReturnsRetained : InheritableAttr { let Spellings = [Clang<"os_returns_retained">]; - let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty]>; + let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty, ParmVar]>; let Documentation = [RetainBehaviorDocs]; } def OSReturnsNotRetained : InheritableAttr { let Spellings = [Clang<"os_returns_not_retained">]; - let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty]>; + let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty, ParmVar]>; + let Documentation = [RetainBehaviorDocs]; +} + +def OSReturnsRetainedOnZero : InheritableAttr { + let Spellings = [Clang<"os_returns_retained_on_zero">]; + let Subjects = SubjectList<[ParmVar]>; + let Documentation = [RetainBehaviorDocs]; +} + +def OSReturnsRetainedOnNonZero : InheritableAttr { + let Spellings = [Clang<"os_returns_retained_on_non_zero">]; + let Subjects = SubjectList<[ParmVar]>; let Documentation = [RetainBehaviorDocs]; } @@ -2867,7 +2880,9 @@ def LoopHint : Attr { /// unroll_count: unrolls loop 'Value' times. /// unroll_and_jam: attempt to unroll and jam loop if State == Enable. /// unroll_and_jam_count: unroll and jams loop 'Value' times. - /// distribute: attempt to distribute loop if State == Enable + /// distribute: attempt to distribute loop if State == Enable. + /// pipeline: disable pipelining loop if State == Disable. + /// pipeline_initiation_interval: create loop schedule with initiation interval equal to 'Value'. /// #pragma unroll <argument> directive /// <no arg>: fully unrolls loop. @@ -2882,10 +2897,10 @@ def LoopHint : Attr { let Args = [EnumArgument<"Option", "OptionType", ["vectorize", "vectorize_width", "interleave", "interleave_count", "unroll", "unroll_count", "unroll_and_jam", "unroll_and_jam_count", - "distribute"], + "pipeline", "pipeline_initiation_interval", "distribute"], ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount", "Unroll", "UnrollCount", "UnrollAndJam", "UnrollAndJamCount", - "Distribute"]>, + "PipelineDisabled", "PipelineInitiationInterval", "Distribute"]>, EnumArgument<"State", "LoopHintState", ["enable", "disable", "numeric", "assume_safety", "full"], ["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>, @@ -2902,6 +2917,8 @@ def LoopHint : Attr { case UnrollCount: return "unroll_count"; case UnrollAndJam: return "unroll_and_jam"; case UnrollAndJamCount: return "unroll_and_jam_count"; + case PipelineDisabled: return "pipeline"; + case PipelineInitiationInterval: return "pipeline_initiation_interval"; case Distribute: return "distribute"; } llvm_unreachable("Unhandled LoopHint option."); @@ -3131,3 +3148,16 @@ def SpeculativeLoadHardening : InheritableAttr { let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>; let Documentation = [SpeculativeLoadHardeningDocs]; } + +def Uninitialized : InheritableAttr { + let Spellings = [Clang<"uninitialized", 0>]; + let Subjects = SubjectList<[LocalVar]>; + let Documentation = [UninitializedDocs]; +} + +def ObjCExternallyRetained : InheritableAttr { + let LangOpts = [ObjCAutoRefCount]; + let Spellings = [Clang<"objc_externally_retained">]; + let Subjects = SubjectList<[NonParmVar, Function, Block, ObjCMethod]>; + let Documentation = [ObjCExternallyRetainedDocs]; +} diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index e72ef253f0..5773a92c9c 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -554,9 +554,9 @@ certain user-defined criteria. For example: .. code-block:: c - void abs(int a) + int abs(int a) __attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning"))); - void must_abs(int a) + int must_abs(int a) __attribute__((diagnose_if(a >= 0, "Redundant abs call", "error"))); int val = abs(1); // warning: Redundant abs call @@ -888,6 +888,21 @@ Similar to ``__attribute__((ns_consumes_self))``, ``__attribute__((os_consumes_this))`` specifies that the method call consumes the reference to "this" (e.g., when attaching it to a different object supplied as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. These attributes are only used by the Clang Static Analyzer. The family of attributes ``X_returns_X_retained`` can be added to functions, @@ -2578,10 +2593,10 @@ def LoopHintDocs : Documentation { let Heading = "#pragma clang loop"; let Content = [{ The ``#pragma clang loop`` directive allows loop optimization hints to be -specified for the subsequent loop. The directive allows vectorization, -interleaving, and unrolling to be enabled or disabled. Vector width as well -as interleave and unrolling count can be manually specified. See -`language extensions +specified for the subsequent loop. The directive allows pipelining to be +disabled, or vectorization, interleaving, and unrolling to be enabled or disabled. +Vector width, interleave count, unrolling count, and the initiation interval +for pipelining can be explicitly specified. See `language extensions <http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_ for details. }]; @@ -2642,6 +2657,56 @@ for further details including limitations of the unroll hints. }]; } +def PipelineHintDocs : Documentation { + let Category = DocCatStmt; + let Heading = "#pragma clang loop pipeline, #pragma clang loop pipeline_initiation_interval"; + let Content = [{ + Software Pipelining optimization is a technique used to optimize loops by + utilizing instruction-level parallelism. It reorders loop instructions to + overlap iterations. As a result, the next iteration starts before the previous + iteration has finished. The module scheduling technique creates a schedule for + one iteration such that when repeating at regular intervals, no inter-iteration + dependencies are violated. This constant interval(in cycles) between the start + of iterations is called the initiation interval. i.e. The initiation interval + is the number of cycles between two iterations of an unoptimized loop in the + newly created schedule. A new, optimized loop is created such that a single iteration + of the loop executes in the same number of cycles as the initiation interval. + For further details see <https://llvm.org/pubs/2005-06-17-LattnerMSThesis-book.pdf>. + + ``#pragma clang loop pipeline and #pragma loop pipeline_initiation_interval`` + could be used as hints for the software pipelining optimization. The pragma is + placed immediately before a for, while, do-while, or a C++11 range-based for + loop. + + Using ``#pragma clang loop pipeline(disable)`` avoids the software pipelining + optimization. The disable state can only be specified: + + .. code-block:: c++ + + #pragma clang loop pipeline(disable) + for (...) { + ... + } + + Using ``#pragma loop pipeline_initiation_interval`` instructs + the software pipeliner to try the specified initiation interval. + If a schedule was found then the resulting loop iteration would have + the specified cycle count. If a schedule was not found then loop + remains unchanged. The initiation interval must be a positive number + greater than zero: + + .. code-block:: c++ + + #pragma loop pipeline_initiation_interval(10) + for (...) { + ... + } + + }]; +} + + + def OpenCLUnrollHintDocs : Documentation { let Category = DocCatStmt; let Content = [{ @@ -3704,6 +3769,18 @@ invoking clang with -fno-c++-static-destructors. }]; } +def UninitializedDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The command-line parameter ``-ftrivial-auto-var-init=*`` can be used to +initialize trivial automatic stack variables. By default, trivial automatic +stack variables are uninitialized. This attribute is used to override the +command-line parameter, forcing variables to remain uninitialized. It has no +semantic meaning in that using uninitialized values is undefined behavior, +it rather documents the programmer's intent. + }]; +} + def GnuInlineDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -3762,3 +3839,31 @@ def SpeculativeLoadHardeningDocs : Documentation { (even after inlining) end up hardened. }]; } + +def ObjCExternallyRetainedDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``objc_externally_retained`` attribute can be applied to strong local +variables, functions, methods, or blocks to opt into +`externally-retained semantics +<https://clang.llvm.org/docs/AutomaticReferenceCounting.html#externally-retained-variables>`_. + +When applied to the definition of a function, method, or block, every parameter +of the function with implicit strong retainable object pointer type is +considered externally-retained, and becomes ``const``. By explicitly annotating +a parameter with ``__strong``, you can opt back into the default +non-externally-retained behaviour for that parameter. For instance, +``first_param`` is externally-retained below, but not ``second_param``: + +.. code-block:: objc + + __attribute__((objc_externally_retained)) + void f(NSArray *first_param, __strong NSArray *second_param) { + // ... + } + +Likewise, when applied to a strong local variable, that variable becomes +``const`` and is considered externally-retained. + +When compiled without ``-fobjc-arc``, this attribute is ignored. +}]; } diff --git a/include/clang/Basic/BuiltinsAMDGPU.def b/include/clang/Basic/BuiltinsAMDGPU.def index 1ee43cb5ee..a25e45fe3f 100644 --- a/include/clang/Basic/BuiltinsAMDGPU.def +++ b/include/clang/Basic/BuiltinsAMDGPU.def @@ -135,13 +135,13 @@ TARGET_BUILTIN(__builtin_amdgcn_fmed3h, "hhhh", "nc", "gfx9-insts") // Deep learning builtins. //===----------------------------------------------------------------------===// -TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hfIb", "nc", "dl-insts") -TARGET_BUILTIN(__builtin_amdgcn_sdot2, "SiV2SsV2SsSiIb", "nc", "dl-insts") -TARGET_BUILTIN(__builtin_amdgcn_udot2, "UiV2UsV2UsUiIb", "nc", "dl-insts") -TARGET_BUILTIN(__builtin_amdgcn_sdot4, "SiSiSiSiIb", "nc", "dl-insts") -TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUiIb", "nc", "dl-insts") -TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dl-insts") -TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dl-insts") +TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hfIb", "nc", "dot-insts") +TARGET_BUILTIN(__builtin_amdgcn_sdot2, "SiV2SsV2SsSiIb", "nc", "dot-insts") +TARGET_BUILTIN(__builtin_amdgcn_udot2, "UiV2UsV2UsUiIb", "nc", "dot-insts") +TARGET_BUILTIN(__builtin_amdgcn_sdot4, "SiSiSiSiIb", "nc", "dot-insts") +TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUiIb", "nc", "dot-insts") +TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dot-insts") +TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dot-insts") //===----------------------------------------------------------------------===// // Special builtins. diff --git a/include/clang/Basic/BuiltinsNios2.def b/include/clang/Basic/BuiltinsNios2.def deleted file mode 100644 index d9697e795c..0000000000 --- a/include/clang/Basic/BuiltinsNios2.def +++ /dev/null @@ -1,70 +0,0 @@ -//===-- BuiltinsNios2.def - Nios2 Builtin function database --------*- 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 Nios2-specific builtin function database. Users of -// this file must define the BUILTIN macro to make use of this information. -// -//===----------------------------------------------------------------------===// - -// The format of this database matches clang/Basic/Builtins.def. - -#if defined(BUILTIN) && !defined(TARGET_BUILTIN) -# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) -#endif - -// Nios2 R1 builtins: - -//int __builtin_ldbio(volatile const void *); -BUILTIN(__builtin_ldbio, "ivDC*", "") -//int __builtin_ldbuio(volatile const void *); -BUILTIN(__builtin_ldbuio, "ivDC*", "") -//int __builtin_ldhio(volatile const void *); -BUILTIN(__builtin_ldhio, "ivDC*", "") -//int __builtin_ldhuio(volatile const void *); -BUILTIN(__builtin_ldhuio, "ivDC*", "") -//int __builtin_ldwio(volatile const void *); -BUILTIN(__builtin_ldwio, "ivDC*", "") -//int __builtin_ldwuio(int); -BUILTIN(__builtin_ldwuio, "ii", "") -// int __builtin_rdctl(int); -BUILTIN(__builtin_rdctl, "iIi", "") -// void __builtin_wrctl(int, int); -BUILTIN(__builtin_wrctl, "vIii", "") -// int __builtin_rdprs(int, int); -BUILTIN(__builtin_rdprs, "iii", "") -//void __builtin_stbio(volatile void *, int); -BUILTIN(__builtin_stbio, "vvD*i", "") -//void __builtin_sthio(volatile void *, int); -BUILTIN(__builtin_sthio, "vvD*i", "") -//void __builtin_stwio(volatile void *, int); -BUILTIN(__builtin_stwio, "vvD*i", "") -//void __builtin_sync(void); -BUILTIN(__builtin_sync, "v", "") -// void __builtin_flushd(volatile void *); -BUILTIN(__builtin_flushd, "vvD*", "") -// void __builtin_flushda(volatile void *); -BUILTIN(__builtin_flushda, "vvD*", "") - -// Nios2 R2 builtins: - -// int __builtin_wrpie(int); -TARGET_BUILTIN(__builtin_wrpie, "ii", "", "nios2r2mandatory") -// void __builtin_eni(int); -TARGET_BUILTIN(__builtin_eni, "vi", "", "nios2r2mandatory") -// int __builtin_ldex(volatile const void *); -TARGET_BUILTIN(__builtin_ldex, "ivDC*", "", "nios2r2mandatory") -// int __builtin_stex(volatile void *, int); -TARGET_BUILTIN(__builtin_stex, "ivD*i", "", "nios2r2mandatory") -// int __builtin_ldsex(volatile const void *); -TARGET_BUILTIN(__builtin_ldsex, "ivDC*", "", "nios2r2mpx") -// int __builtin_stsex(volatile void *, int); -TARGET_BUILTIN(__builtin_stsex, "ivDC*i", "", "nios2r2mpx") - -#undef BUILTIN -#undef TARGET_BUILTIN diff --git a/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def index e1e97fe26a..55931edc5c 100644 --- a/include/clang/Basic/BuiltinsWebAssembly.def +++ b/include/clang/Basic/BuiltinsWebAssembly.def @@ -16,23 +16,25 @@ // The format of this database matches clang/Basic/Builtins.def. +#if defined(BUILTIN) && !defined(TARGET_BUILTIN) +# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) +#endif + // Query the current memory size, and increase the current memory size. // Note that memory.size is not "c" (readnone) because it must be sequenced // with respect to memory.grow calls. BUILTIN(__builtin_wasm_memory_size, "zIi", "n") BUILTIN(__builtin_wasm_memory_grow, "zIiz", "n") -// These are the old names. -BUILTIN(__builtin_wasm_mem_size, "zIi", "n") -BUILTIN(__builtin_wasm_mem_grow, "zIiz", "n") - -// These are the old old names. They also lack the immediate field. -BUILTIN(__builtin_wasm_current_memory, "z", "n") -BUILTIN(__builtin_wasm_grow_memory, "zz", "n") +// Floating point min/max +BUILTIN(__builtin_wasm_min_f32, "fff", "nc") +BUILTIN(__builtin_wasm_max_f32, "fff", "nc") +BUILTIN(__builtin_wasm_min_f64, "ddd", "nc") +BUILTIN(__builtin_wasm_max_f64, "ddd", "nc") // Exception handling builtins. -BUILTIN(__builtin_wasm_throw, "vUiv*", "r") -BUILTIN(__builtin_wasm_rethrow, "v", "r") +TARGET_BUILTIN(__builtin_wasm_throw, "vUiv*", "r", "exception-handling") +TARGET_BUILTIN(__builtin_wasm_rethrow, "v", "r", "exception-handling") // Atomic wait and notify. BUILTIN(__builtin_wasm_atomic_wait_i32, "ii*iLLi", "n") @@ -40,73 +42,68 @@ BUILTIN(__builtin_wasm_atomic_wait_i64, "iLLi*LLiLLi", "n") BUILTIN(__builtin_wasm_atomic_notify, "Uii*Ui", "n") // Saturating fp-to-int conversions -BUILTIN(__builtin_wasm_trunc_saturate_s_i32_f32, "if", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_u_i32_f32, "if", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_s_i32_f64, "id", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_u_i32_f64, "id", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_s_i64_f32, "LLif", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_u_i64_f32, "LLif", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_s_i64_f64, "LLid", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_u_i64_f64, "LLid", "nc") - -// Floating point min/max -BUILTIN(__builtin_wasm_min_f32, "fff", "nc") -BUILTIN(__builtin_wasm_max_f32, "fff", "nc") -BUILTIN(__builtin_wasm_min_f64, "ddd", "nc") -BUILTIN(__builtin_wasm_max_f64, "ddd", "nc") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32_f32, "if", "nc", "nontrapping-fptoint") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32_f32, "if", "nc", "nontrapping-fptoint") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32_f64, "id", "nc", "nontrapping-fptoint") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32_f64, "id", "nc", "nontrapping-fptoint") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64_f32, "LLif", "nc", "nontrapping-fptoint") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64_f32, "LLif", "nc", "nontrapping-fptoint") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64_f64, "LLid", "nc", "nontrapping-fptoint") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64_f64, "LLid", "nc", "nontrapping-fptoint") // SIMD builtins -BUILTIN(__builtin_wasm_extract_lane_s_i8x16, "iV16cIi", "nc") -BUILTIN(__builtin_wasm_extract_lane_u_i8x16, "iV16cIi", "nc") -BUILTIN(__builtin_wasm_extract_lane_s_i16x8, "iV8sIi", "nc") -BUILTIN(__builtin_wasm_extract_lane_u_i16x8, "iV8sIi", "nc") -BUILTIN(__builtin_wasm_extract_lane_i32x4, "iV4iIi", "nc") -BUILTIN(__builtin_wasm_extract_lane_i64x2, "LLiV2LLiIi", "nc") -BUILTIN(__builtin_wasm_extract_lane_f32x4, "fV4fIi", "nc") -BUILTIN(__builtin_wasm_extract_lane_f64x2, "dV2dIi", "nc") - -BUILTIN(__builtin_wasm_replace_lane_i8x16, "V16cV16cIii", "nc") -BUILTIN(__builtin_wasm_replace_lane_i16x8, "V8sV8sIii", "nc") -BUILTIN(__builtin_wasm_replace_lane_i32x4, "V4iV4iIii", "nc") -BUILTIN(__builtin_wasm_replace_lane_i64x2, "V2LLiV2LLiIiLLi", "nc") -BUILTIN(__builtin_wasm_replace_lane_f32x4, "V4fV4fIif", "nc") -BUILTIN(__builtin_wasm_replace_lane_f64x2, "V2dV2dIid", "nc") - -BUILTIN(__builtin_wasm_add_saturate_s_i8x16, "V16cV16cV16c", "nc") -BUILTIN(__builtin_wasm_add_saturate_u_i8x16, "V16cV16cV16c", "nc") -BUILTIN(__builtin_wasm_add_saturate_s_i16x8, "V8sV8sV8s", "nc") -BUILTIN(__builtin_wasm_add_saturate_u_i16x8, "V8sV8sV8s", "nc") - -BUILTIN(__builtin_wasm_sub_saturate_s_i8x16, "V16cV16cV16c", "nc") -BUILTIN(__builtin_wasm_sub_saturate_u_i8x16, "V16cV16cV16c", "nc") -BUILTIN(__builtin_wasm_sub_saturate_s_i16x8, "V8sV8sV8s", "nc") -BUILTIN(__builtin_wasm_sub_saturate_u_i16x8, "V8sV8sV8s", "nc") - -BUILTIN(__builtin_wasm_bitselect, "V4iV4iV4iV4i", "nc") - -BUILTIN(__builtin_wasm_any_true_i8x16, "iV16c", "nc") -BUILTIN(__builtin_wasm_any_true_i16x8, "iV8s", "nc") -BUILTIN(__builtin_wasm_any_true_i32x4, "iV4i", "nc") -BUILTIN(__builtin_wasm_any_true_i64x2, "iV2LLi", "nc") -BUILTIN(__builtin_wasm_all_true_i8x16, "iV16c", "nc") -BUILTIN(__builtin_wasm_all_true_i16x8, "iV8s", "nc") -BUILTIN(__builtin_wasm_all_true_i32x4, "iV4i", "nc") -BUILTIN(__builtin_wasm_all_true_i64x2, "iV2LLi", "nc") - -BUILTIN(__builtin_wasm_abs_f32x4, "V4fV4f", "nc") -BUILTIN(__builtin_wasm_abs_f64x2, "V2dV2d", "nc") - -BUILTIN(__builtin_wasm_min_f32x4, "V4fV4fV4f", "nc") -BUILTIN(__builtin_wasm_max_f32x4, "V4fV4fV4f", "nc") -BUILTIN(__builtin_wasm_min_f64x2, "V2dV2dV2d", "nc") -BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc") - -BUILTIN(__builtin_wasm_sqrt_f32x4, "V4fV4f", "nc") -BUILTIN(__builtin_wasm_sqrt_f64x2, "V2dV2d", "nc") - -BUILTIN(__builtin_wasm_trunc_saturate_s_i32x4_f32x4, "V4iV4f", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_u_i32x4_f32x4, "V4iV4f", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_s_i64x2_f64x2, "V2LLiV2d", "nc") -BUILTIN(__builtin_wasm_trunc_saturate_u_i64x2_f64x2, "V2LLiV2d", "nc") +TARGET_BUILTIN(__builtin_wasm_extract_lane_s_i8x16, "iV16cIi", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_extract_lane_u_i8x16, "iV16cIi", "nc", "unimplemented-simd128") +TARGET_BUILTIN(__builtin_wasm_extract_lane_s_i16x8, "iV8sIi", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_extract_lane_u_i16x8, "iV8sIi", "nc", "unimplemented-simd128") +TARGET_BUILTIN(__builtin_wasm_extract_lane_i32x4, "iV4iIi", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_extract_lane_i64x2, "LLiV2LLiIi", "nc", "unimplemented-simd128") +TARGET_BUILTIN(__builtin_wasm_extract_lane_f32x4, "fV4fIi", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_extract_lane_f64x2, "dV2dIi", "nc", "unimplemented-simd128") + +TARGET_BUILTIN(__builtin_wasm_replace_lane_i8x16, "V16cV16cIii", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_replace_lane_i16x8, "V8sV8sIii", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_replace_lane_i32x4, "V4iV4iIii", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_replace_lane_i64x2, "V2LLiV2LLiIiLLi", "nc", "unimplemented-simd128") +TARGET_BUILTIN(__builtin_wasm_replace_lane_f32x4, "V4fV4fIif", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_replace_lane_f64x2, "V2dV2dIid", "nc", "unimplemented-simd128") + +TARGET_BUILTIN(__builtin_wasm_add_saturate_s_i8x16, "V16cV16cV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_add_saturate_u_i8x16, "V16cV16cV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_add_saturate_s_i16x8, "V8sV8sV8s", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_add_saturate_u_i16x8, "V8sV8sV8s", "nc", "simd128") + +TARGET_BUILTIN(__builtin_wasm_sub_saturate_s_i8x16, "V16cV16cV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i8x16, "V16cV16cV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_sub_saturate_s_i16x8, "V8sV8sV8s", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i16x8, "V8sV8sV8s", "nc", "simd128") + +TARGET_BUILTIN(__builtin_wasm_bitselect, "V4iV4iV4iV4i", "nc", "simd128") + +TARGET_BUILTIN(__builtin_wasm_any_true_i8x16, "iV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_any_true_i16x8, "iV8s", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_any_true_i32x4, "iV4i", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_any_true_i64x2, "iV2LLi", "nc", "unimplemented-simd128") +TARGET_BUILTIN(__builtin_wasm_all_true_i8x16, "iV16c", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_all_true_i16x8, "iV8s", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_all_true_i32x4, "iV4i", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_all_true_i64x2, "iV2LLi", "nc", "unimplemented-simd128") + +TARGET_BUILTIN(__builtin_wasm_abs_f32x4, "V4fV4f", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_abs_f64x2, "V2dV2d", "nc", "unimplemented-simd128") + +TARGET_BUILTIN(__builtin_wasm_min_f32x4, "V4fV4fV4f", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_max_f32x4, "V4fV4fV4f", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_min_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd128") +TARGET_BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd128") + +TARGET_BUILTIN(__builtin_wasm_sqrt_f32x4, "V4fV4f", "nc", "unimplemented-simd128") +TARGET_BUILTIN(__builtin_wasm_sqrt_f64x2, "V2dV2d", "nc", "unimplemented-simd128") + +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32x4_f32x4, "V4iV4f", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32x4_f32x4, "V4iV4f", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64x2_f64x2, "V2LLiV2d", "nc", "unimplemented-simd128") +TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64x2_f64x2, "V2LLiV2d", "nc", "unimplemented-simd128") #undef BUILTIN +#undef TARGET_BUILTIN diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index d97ec58916..b3564b957e 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -968,47 +968,47 @@ TARGET_BUILTIN(__builtin_ia32_vpdpwssds128, "V4iV4iV4iV4i", "ncV:128:", "avx512v TARGET_BUILTIN(__builtin_ia32_vpdpwssds256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni") TARGET_BUILTIN(__builtin_ia32_vpdpwssds512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8ffC*V8LLiUcIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLiLLiC*V8iUcIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16iiC*V16iUsIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLiLLiC*V8LLiUcIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8iiC*V8LLiUcIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vd*UcV8iV8dIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vf*UsV16iV16fIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vd*UcV8LLiV8dIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vf*UcV8LLiV8fIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vLLi*UcV8iV8LLiIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vi*UsV16iV16iIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vLLi*UcV8LLiV8LLiIi", "nV:512:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vi*UcV8LLiV8iIi", "nV:512:", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8iLLiC*IiIi", "nV:512:", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16iiC*IiIi", "nV:512:", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLiLLiC*IiIi", "nV:512:", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLiiC*IiIi", "nV:512:", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iLLi*IiIi", "nV:512:", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16ii*IiIi", "nV:512:", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiLLi*IiIi", "nV:512:", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLii*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2dvC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLivC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4dvC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLivC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4fvC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4ivC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4fvC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4ivC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2dvC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLivC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4dvC*V4iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLivC*V4iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4fvC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4ivC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8fvC*V8iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8ivC*V8iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8dvC*V8iUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16fvC*V16iUsIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8dvC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8fvC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLivC*V8iUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16ivC*V16iUsIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLivC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8ivC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vv*UcV8iV8dIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vv*UsV16iV16fIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vv*UcV8LLiV8dIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vv*UcV8LLiV8fIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vv*UcV8iV8LLiIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vv*UsV16iV16iIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vv*UcV8LLiV8LLiIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vv*UcV8LLiV8iIi", "nV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8ivC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16ivC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLivC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLivC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iv*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16iv*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*IiIi", "nV:512:", "avx512pf") TARGET_BUILTIN(__builtin_ia32_knotqi, "UcUc", "nc", "avx512dq") TARGET_BUILTIN(__builtin_ia32_knothi, "UsUs", "nc", "avx512f") @@ -1210,22 +1210,22 @@ TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "ncV:256:", "a TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512vl") TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "ncV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vd*UcV2LLiV2dIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vLLi*UcV2LLiV2LLiIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vd*UcV4LLiV4dIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vLLi*UcV4LLiV4LLiIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vf*UcV2LLiV4fIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vi*UcV2LLiV4iIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vf*UcV4LLiV4fIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vi*UcV4LLiV4iIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vd*UcV4iV2dIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vLLi*UcV4iV2LLiIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vd*UcV4iV4dIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vLLi*UcV4iV4LLiIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vf*UcV4iV4fIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vi*UcV4iV4iIi", "nV:128:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vf*UcV8iV8fIi", "nV:256:", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vi*UcV8iV8iIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vv*UcV2LLiV2dIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vv*UcV2LLiV2LLiIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vv*UcV4LLiV4dIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vv*UcV4LLiV4LLiIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vv*UcV2LLiV4fIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vv*UcV2LLiV4iIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vv*UcV4LLiV4fIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vv*UcV4LLiV4iIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vv*UcV4iV2dIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vv*UcV4iV2LLiIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vv*UcV4iV4dIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vv*UcV4iV4LLiIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vv*UcV4iV4fIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vv*UcV4iV4iIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vv*UcV8iV8fIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vv*UcV8iV8iIi", "nV:256:", "avx512vl") TARGET_BUILTIN(__builtin_ia32_vpermi2vard128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl") TARGET_BUILTIN(__builtin_ia32_vpermi2vard256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl") @@ -1256,43 +1256,25 @@ TARGET_BUILTIN(__builtin_ia32_vpshldw128, "V8sV8sV8sIi", "ncV:128:", "avx512vl,a TARGET_BUILTIN(__builtin_ia32_vpshldw256, "V16sV16sV16sIi", "ncV:256:", "avx512vl,avx512vbmi2") TARGET_BUILTIN(__builtin_ia32_vpshldw512, "V32sV32sV32sIi", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw128, "V8sV8sV8sV8s", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw256, "V16sV16sV16sV16s", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw512, "V32sV32sV32sV32s", "ncV:512:", "avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_vpshrdvd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw128, "V8sV8sV8sV8s", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw256, "V16sV16sV16sV16s", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw512, "V32sV32sV32sV32s", "ncV:512:", "avx512vbmi2") TARGET_BUILTIN(__builtin_ia32_vpshrdd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl,avx512vbmi2") TARGET_BUILTIN(__builtin_ia32_vpshrdd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl,avx512vbmi2") @@ -1839,9 +1821,9 @@ TARGET_BUILTIN(__builtin_ia32_cvtsd2ss_round_mask, "V4fV4fV2dV4fUcIi", "ncV:128: TARGET_BUILTIN(__builtin_ia32_cvtsi2ss32, "V4fV4fiIi", "ncV:128:", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtss2sd_round_mask, "V2dV2dV4fV2dUcIi", "ncV:128:", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtusi2ss32, "V4fV4fUiIi", "ncV:128:", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512vbmi") -TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128_mask, "V16cV16cV16cV16cUs", "ncV:128:", "avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256_mask, "V32cV32cV32cV32cUi", "ncV:256:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512, "V64cV64cV64c", "ncV:512:", "avx512vbmi") +TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128, "V16cV16cV16c", "ncV:128:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256, "V32cV32cV32c", "ncV:256:", "avx512vbmi,avx512vl") // generic select intrinsics TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "ncV:128:", "avx512bw,avx512vl") diff --git a/include/clang/Basic/CodeGenOptions.def b/include/clang/Basic/CodeGenOptions.def index 952aa588b6..ed2387b9a2 100644 --- a/include/clang/Basic/CodeGenOptions.def +++ b/include/clang/Basic/CodeGenOptions.def @@ -116,6 +116,10 @@ CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the ///< compile step. CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole ///< program vtable opt). +CODEGENOPT(EnableSplitLTOUnit, 1, 0) ///< Enable LTO unit splitting to support + /// CFI and traditional whole program + /// devirtualization that require whole + /// program IR support. CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can ///< be used with an incremental ///< linker. diff --git a/include/clang/Basic/CodeGenOptions.h b/include/clang/Basic/CodeGenOptions.h index a12744ee3d..ec6eda7fb7 100644 --- a/include/clang/Basic/CodeGenOptions.h +++ b/include/clang/Basic/CodeGenOptions.h @@ -286,6 +286,8 @@ public: /// Set of XRay instrumentation kinds to emit. XRayInstrSet XRayInstrumentationBundle; + std::vector<std::string> DefaultFunctionAttrs; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index d7e1c62890..a516721ace 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -177,6 +177,9 @@ public: /// IdentifierInfo ak_identifierinfo, + /// Qualifiers + ak_qual, + /// QualType ak_qualtype, diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 5a3378c869..34ce489e50 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -290,4 +290,10 @@ def err_openclcxx_not_supported : Error< // OpenMP def err_omp_more_one_clause : Error< "directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">; + +// Static Analyzer Core +def err_unknown_analyzer_checker : Error< + "no analyzer checkers are associated with '%0'">; +def note_suggest_disabling_all_checkers : Note< + "use -analyzer-disable-all-checks to disable all static analyzer checkers">; } diff --git a/include/clang/Basic/DiagnosticCrossTUKinds.td b/include/clang/Basic/DiagnosticCrossTUKinds.td index 9c432457df..89e261c84b 100644 --- a/include/clang/Basic/DiagnosticCrossTUKinds.td +++ b/include/clang/Basic/DiagnosticCrossTUKinds.td @@ -12,7 +12,7 @@ let Component = "CrossTU" in { def err_ctu_error_opening : Error< "error opening '%0': required by the CrossTU functionality">; -def err_fnmap_parsing : Error< +def err_extdefmap_parsing : Error< "error parsing index file: '%0' line: %1 'UniqueID filename' format " "expected">; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index af528e1718..5475e28ed7 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -405,4 +405,24 @@ def warn_drv_experimental_isel_incomplete_opt : Warning< def warn_drv_moutline_unsupported_opt : Warning< "The '%0' architecture does not support -moutline; flag ignored">, InGroup<OptionIgnored>; + +def warn_drv_darwin_sdk_invalid_settings : Warning< + "SDK settings were ignored as 'SDKSettings.json' could not be parsed">, + InGroup<DiagGroup<"darwin-sdk-settings">>; + +def err_drv_trivial_auto_var_init_zero_disabled : Error< + "-ftrivial-auto-var-init=zero hasn't been enabled. Enable it at your own peril for benchmarking purpose only with " + "-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang">; + +def warn_drv_msp430_hwmult_unsupported : Warning<"the given MCU does not " + "support hardware multiply, but -mhwmult is set to %0.">, + InGroup<InvalidCommandLineArgument>; +def warn_drv_msp430_hwmult_mismatch : Warning<"the given MCU supports %0 " + "hardware multiply, but -mhwmult is set to %1.">, + InGroup<InvalidCommandLineArgument>; +def warn_drv_msp430_hwmult_no_device : Warning<"no MCU device specified, but " + "'-mhwmult' is set to 'auto', assuming no hardware multiply. Use -mmcu to " + "specify a MSP430 device, or -mhwmult to set hardware multiply type " + "explicitly.">, InGroup<InvalidCommandLineArgument>; + } diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index b2fcb9ca14..927b8cbc24 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -160,11 +160,6 @@ def warn_unknown_warning_specifier : Warning< "unknown %0 warning specifier: '%1'">, InGroup<UnknownWarningOption>; -def err_unknown_analyzer_checker : Error< - "no analyzer checkers are associated with '%0'">; -def note_suggest_disabling_all_checkers : Note< - "use -analyzer-disable-all-checks to disable all static analyzer checkers">; - def warn_incompatible_analyzer_plugin_api : Warning< "checker plugin '%0' is not compatible with this version of the analyzer">, InGroup<DiagGroup<"analyzer-incompatible-plugin"> >; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 6ba6c19a28..19e187cc5d 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -104,7 +104,11 @@ def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">; def MissingNoEscape : DiagGroup<"missing-noescape">; def DeleteIncomplete : DiagGroup<"delete-incomplete">; -def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">; +def DeleteNonAbstractNonVirtualDtor : DiagGroup<"delete-non-abstract-non-virtual-dtor">; +def DeleteAbstractNonVirtualDtor : DiagGroup<"delete-abstract-non-virtual-dtor">; +def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor", + [DeleteNonAbstractNonVirtualDtor, + DeleteAbstractNonVirtualDtor]>; def AbstractFinalClass : DiagGroup<"abstract-final-class">; def CXX11CompatDeprecatedWritableStr : @@ -361,6 +365,8 @@ def NullArithmetic : DiagGroup<"null-arithmetic">; def NullCharacter : DiagGroup<"null-character">; def NullDereference : DiagGroup<"null-dereference">; def InitializerOverrides : DiagGroup<"initializer-overrides">; +// For compatibility with GCC; -Woverride-init = -Winitializer-overrides +def : DiagGroup<"override-init", [InitializerOverrides]>; def NonNull : DiagGroup<"nonnull">; def NonPODVarargs : DiagGroup<"non-pod-varargs">; def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index ec07bb5c4f..06281e2904 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -1100,6 +1100,13 @@ def err_pragma_attribute_unknown_subject_sub_rule : Error< "sub-rules: %3}2">; def err_pragma_attribute_duplicate_subject : Error< "duplicate attribute subject matcher '%0'">; +def err_pragma_attribute_expected_period : Error< + "expected '.' after pragma attribute namespace %0">; +def err_pragma_attribute_namespace_on_attribute : Error< + "namespace can only apply to 'push' or 'pop' directives">; +def note_pragma_attribute_namespace_on_attribute : Note< + "omit the namespace to add attributes to the most-recently" + " pushed attribute group">; def err_opencl_unroll_hint_on_non_loop : Error< "OpenCL only supports 'opencl_unroll_hint' attribute on for, while, and do statements">; @@ -1157,9 +1164,11 @@ def err_omp_decl_in_declare_simd : Error< def err_omp_unknown_map_type : Error< "incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">; def err_omp_unknown_map_type_modifier : Error< - "incorrect map type modifier, expected 'always'">; + "incorrect map type modifier, expected 'always' or 'close'">; def err_omp_map_type_missing : Error< "missing map type">; +def err_omp_map_type_modifier_missing : Error< + "missing map type modifier">; def err_omp_declare_simd_inbranch_notinbranch : Error< "unexpected '%0' clause, '%1' is specified already">; def err_expected_end_declare_target : Error< @@ -1175,7 +1184,8 @@ def err_pragma_loop_missing_argument : Error< "'enable'%select{|, 'full'}1%select{|, 'assume_safety'}2 or 'disable'}0">; def err_pragma_loop_invalid_option : Error< "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, " - "vectorize_width, interleave, interleave_count, unroll, unroll_count, or distribute">; + "vectorize_width, interleave, interleave_count, unroll, unroll_count, " + "pipeline, pipeline_initiation_interval, or distribute">; def err_pragma_fp_invalid_option : Error< "%select{invalid|missing}0 option%select{ %1|}0; expected contract">; @@ -1188,6 +1198,8 @@ def err_pragma_fp_scope : Error< def err_pragma_invalid_keyword : Error< "invalid argument; expected 'enable'%select{|, 'full'}0%select{|, 'assume_safety'}1 or 'disable'">; +def err_pragma_pipeline_invalid_keyword : Error< + "invalid argument; expected 'disable'">; // Pragma unroll support. def warn_pragma_unroll_cuda_value_in_parens : Warning< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2e84f5fedf..5feb877e46 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -815,7 +815,8 @@ def err_pragma_attribute_matcher_negated_subrule_contradicts_subrule : Error< def err_pragma_attribute_invalid_matchers : Error< "attribute %0 can't be applied to %1">; def err_pragma_attribute_stack_mismatch : Error< - "'#pragma clang attribute pop' with no matching '#pragma clang attribute push'">; + "'#pragma clang attribute %select{%1.|}0pop' with no matching" + " '#pragma clang attribute %select{%1.|}0push'">; def warn_pragma_attribute_unused : Warning< "unused attribute %0 in '#pragma clang attribute push' region">, InGroup<PragmaClangAttribute>; @@ -1297,8 +1298,8 @@ def ext_unelaborated_friend_type : ExtWarn< def warn_cxx98_compat_unelaborated_friend_type : Warning< "befriending %1 without '%select{struct|interface|union|class|enum}0' " "keyword is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; -def err_qualified_friend_not_found : Error< - "no function named %0 with type %1 was found in the specified scope">; +def err_qualified_friend_no_match : Error< + "friend declaration of %0 does not match any declaration in %1">; def err_introducing_special_friend : Error< "%plural{[0,2]:must use a qualified name when declaring|3:cannot declare}0" " a %select{constructor|destructor|conversion operator|deduction guide}0 " @@ -1808,11 +1809,7 @@ def err_init_conversion_failed : Error< "|: different number of parameters (%5 vs %6)" "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7" "|: different return type%diff{ ($ vs $)|}5,6" - "|: different qualifiers (" - "%select{none|const|restrict|const and restrict|volatile|const and volatile|" - "volatile and restrict|const, volatile, and restrict}5 vs " - "%select{none|const|restrict|const and restrict|volatile|const and volatile|" - "volatile and restrict|const, volatile, and restrict}6)" + "|: different qualifiers (%5 vs %6)" "|: different exception specifications}4">; def err_lvalue_to_rvalue_ref : Error<"rvalue reference %diff{to type $ cannot " @@ -3428,7 +3425,7 @@ def err_ns_attribute_wrong_parameter_type : Error< "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">; def warn_ns_attribute_wrong_parameter_type : Warning< "%0 attribute only applies to " - "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">, + "%select{Objective-C object|pointer|pointer-to-CF-pointer|pointer/reference-to-OSObject-pointer}1 parameters">, InGroup<IgnoredAttributes>; def warn_objc_requires_super_protocol : Warning< "%0 attribute cannot be applied to %select{methods in protocols|dealloc}1">, @@ -3488,6 +3485,11 @@ def err_objc_bridged_related_known_method : Error< def err_objc_attr_protocol_requires_definition : Error< "attribute %0 can only be applied to @protocol definitions, not forward declarations">; +def warn_ignored_objc_externally_retained : Warning< + "'objc_externally_retained' can only be applied to local variables " + "%select{of retainable type|with strong ownership}0">, + InGroup<IgnoredAttributes>; + // Function Parameter Semantic Analysis. def err_param_with_void_type : Error<"argument may not have 'void' type">; def err_void_only_param : Error< @@ -3592,11 +3594,7 @@ def note_ovl_candidate : Note< "| has type mismatch at %ordinal5 parameter" "%diff{ (expected $ but has $)|}6,7" "| has different return type%diff{ ($ expected but has $)|}5,6" - "| has different qualifiers (expected " - "%select{none|const|restrict|const and restrict|volatile|const and volatile" - "|volatile and restrict|const, volatile, and restrict}5 but found " - "%select{none|const|restrict|const and restrict|volatile|const and volatile" - "|volatile and restrict|const, volatile, and restrict}6)" + "| has different qualifiers (expected %5 but found %6)" "| has different exception specification}4">; def note_ovl_candidate_inherited_constructor : Note< @@ -4567,7 +4565,10 @@ def warn_unavailable_fwdclass_message : Warning< InGroup<UnavailableDeclarations>; def note_availability_specified_here : Note< "%0 has been explicitly marked " - "%select{unavailable|deleted|deprecated|partial}1 here">; + "%select{unavailable|deleted|deprecated}1 here">; +def note_partial_availability_specified_here : Note< + "%0 has been marked as being introduced in %1 %2 here, " + "but the deployment target is %1 %3">; def note_implicitly_deleted : Note< "explicitly defaulted function was implicitly deleted here">; def warn_not_enough_argument : Warning< @@ -4880,7 +4881,7 @@ def warn_braces_around_scalar_init : Warning< "braces around scalar initializer">, InGroup<DiagGroup<"braced-scalar-init">>; def ext_many_braces_around_scalar_init : ExtWarn< "too many braces around scalar initializer">, - InGroup<DiagGroup<"many-braces-around-scalar-init">>; + InGroup<DiagGroup<"many-braces-around-scalar-init">>, SFINAEFailure; def ext_complex_component_init : Extension< "complex initialization specifying real and imaginary components " "is an extension">, InGroup<DiagGroup<"complex-component-init">>; @@ -5261,6 +5262,9 @@ def err_typecheck_arc_assign_self_class_method : Error< def err_typecheck_arr_assign_enumeration : Error< "fast enumeration variables cannot be modified in ARC by default; " "declare the variable __strong to allow this">; +def err_typecheck_arc_assign_externally_retained : Error< + "variable declared with 'objc_externally_retained' " + "cannot be modified in ARC">; def warn_arc_retained_assign : Warning< "assigning retained object to %select{weak|unsafe_unretained}0 " "%select{property|variable}1" @@ -5874,7 +5878,8 @@ def ext_typecheck_comparison_of_fptr_to_void : Extension< def err_typecheck_comparison_of_fptr_to_void : Error< "equality comparison between function pointer and void pointer (%0 and %1)">; def ext_typecheck_comparison_of_pointer_integer : ExtWarn< - "comparison between pointer and integer (%0 and %1)">; + "comparison between pointer and integer (%0 and %1)">, + InGroup<DiagGroup<"pointer-integer-compare">>; def err_typecheck_comparison_of_pointer_integer : Error< "comparison between pointer and integer (%0 and %1)">; def ext_typecheck_comparison_of_distinct_pointers : ExtWarn< @@ -6454,12 +6459,12 @@ def warn_non_virtual_dtor : Warning< def warn_delete_non_virtual_dtor : Warning< "%select{delete|destructor}0 called on non-final %1 that has " "virtual functions but non-virtual destructor">, - InGroup<DeleteNonVirtualDtor>, DefaultIgnore, ShowInSystemHeader; + InGroup<DeleteNonAbstractNonVirtualDtor>, DefaultIgnore, ShowInSystemHeader; def note_delete_non_virtual : Note< "qualify call to silence this warning">; def warn_delete_abstract_non_virtual_dtor : Warning< "%select{delete|destructor}0 called on %1 that is abstract but has " - "non-virtual destructor">, InGroup<DeleteNonVirtualDtor>, ShowInSystemHeader; + "non-virtual destructor">, InGroup<DeleteAbstractNonVirtualDtor>, ShowInSystemHeader; def warn_overloaded_virtual : Warning< "%q0 hides overloaded virtual %select{function|functions}1">, InGroup<OverloadedVirtual>, DefaultIgnore; @@ -6469,11 +6474,7 @@ def note_hidden_overloaded_virtual_declared_here : Note< "|: different number of parameters (%2 vs %3)" "|: type mismatch at %ordinal2 parameter%diff{ ($ vs $)|}3,4" "|: different return type%diff{ ($ vs $)|}2,3" - "|: different qualifiers (" - "%select{none|const|restrict|const and restrict|volatile|const and volatile|" - "volatile and restrict|const, volatile, and restrict}2 vs " - "%select{none|const|restrict|const and restrict|volatile|const and volatile|" - "volatile and restrict|const, volatile, and restrict}3)" + "|: different qualifiers (%2 vs %3)" "|: different exception specifications}1">; def warn_using_directive_in_header : Warning< "using namespace directive in global context in header">, @@ -6747,11 +6748,7 @@ def err_typecheck_convert_incompatible : Error< "|: different number of parameters (%5 vs %6)" "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7" "|: different return type%diff{ ($ vs $)|}5,6" - "|: different qualifiers (" - "%select{none|const|restrict|const and restrict|volatile|const and volatile|" - "volatile and restrict|const, volatile, and restrict}5 vs " - "%select{none|const|restrict|const and restrict|volatile|const and volatile|" - "volatile and restrict|const, volatile, and restrict}6)" + "|: different qualifiers (%5 vs %6)" "|: different exception specifications}4">; def err_typecheck_missing_return_type_incompatible : Error< "%diff{return type $ must match previous return type $|" @@ -8725,6 +8722,8 @@ def err_omp_expected_access_to_data_field : Error< "expected access to data field">; def err_omp_multiple_array_items_in_map_clause : Error< "multiple array elements associated with the same variable are not allowed in map clauses of the same construct">; +def err_omp_duplicate_map_type_modifier : Error< + "same map type modifier has been specified more than once">; def err_omp_pointer_mapped_along_with_derived_section : Error< "pointer cannot be mapped along with a section derived from itself">; def err_omp_original_storage_is_shared_and_does_not_contain : Error< @@ -8783,8 +8782,10 @@ def err_omp_required_access : Error< "%0 variable must be %1">; def err_omp_const_variable : Error< "const-qualified variable cannot be %0">; -def err_omp_const_reduction_list_item : Error< - "const-qualified list item cannot be reduction">; +def err_omp_const_not_mutable_variable : Error< + "const-qualified variable without mutable fields cannot be %0">; +def err_omp_const_list_item : Error< + "const-qualified list item cannot be %0">; def err_omp_linear_incomplete_type : Error< "a linear variable with incomplete type %0">; def err_omp_linear_expected_int_or_ptr : Error< @@ -9073,6 +9074,14 @@ def note_omp_requires_previous_clause : Note < "%0 clause previously used here">; def err_omp_invalid_scope : Error < "'#pragma omp %0' directive must appear only in file scope">; +def note_omp_invalid_length_on_this_ptr_mapping : Note < + "expected length on mapping of 'this' array section expression to be '1'">; +def note_omp_invalid_lower_bound_on_this_ptr_mapping : Note < + "expected lower bound on mapping of 'this' array section expression to be '0' or not specified">; +def note_omp_invalid_subscript_on_this_ptr_map : Note < + "expected 'this' subscript expression on map clause to be 'this[0]'">; +def err_omp_invalid_map_this_expr : Error < + "invalid 'this' expression on 'map' clause">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { diff --git a/include/clang/Basic/Features.def b/include/clang/Basic/Features.def index 0cece27eef..05464ed85f 100644 --- a/include/clang/Basic/Features.def +++ b/include/clang/Basic/Features.def @@ -17,6 +17,12 @@ // // The Predicate field dictates the conditions under which the feature or // extension will be made available. +// +// FEATURE(...) should be used to advertise support for standard language +// features, whereas EXTENSION(...) should be used for clang extensions. Note +// that many of the identifiers in this file don't follow this rule for backward +// compatibility reasons. +// //===----------------------------------------------------------------------===// #if !defined(FEATURE) && !defined(EXTENSION) @@ -240,6 +246,7 @@ EXTENSION(cxx_init_captures, LangOpts.CPlusPlus11) EXTENSION(cxx_variable_templates, LangOpts.CPlusPlus) // Miscellaneous language extensions EXTENSION(overloadable_unmarked, true) +EXTENSION(pragma_clang_attribute_namespaces, true) #undef EXTENSION #undef FEATURE diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 8e021f41c1..e7891baf53 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -192,18 +192,10 @@ public: /// /// \param statCache the new stat cache to install. Ownership of this /// object is transferred to the FileManager. - /// - /// \param AtBeginning whether this new stat cache must be installed at the - /// beginning of the chain of stat caches. Otherwise, it will be added to - /// the end of the chain. - void addStatCache(std::unique_ptr<FileSystemStatCache> statCache, - bool AtBeginning = false); - - /// Removes the specified FileSystemStatCache object from the manager. - void removeStatCache(FileSystemStatCache *statCache); + void setStatCache(std::unique_ptr<FileSystemStatCache> statCache); - /// Removes all FileSystemStatCache objects from the manager. - void clearStatCaches(); + /// Removes the FileSystemStatCache object from the manager. + void clearStatCache(); /// Lookup, cache, and verify the specified directory (real or /// virtual). diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h index a0277009d7..f93170c754 100644 --- a/include/clang/Basic/FileSystemStatCache.h +++ b/include/clang/Basic/FileSystemStatCache.h @@ -60,9 +60,6 @@ struct FileData { class FileSystemStatCache { virtual void anchor(); -protected: - std::unique_ptr<FileSystemStatCache> NextStatCache; - public: virtual ~FileSystemStatCache() = default; @@ -88,22 +85,6 @@ public: std::unique_ptr<llvm::vfs::File> *F, FileSystemStatCache *Cache, llvm::vfs::FileSystem &FS); - /// Sets the next stat call cache in the chain of stat caches. - /// Takes ownership of the given stat cache. - void setNextStatCache(std::unique_ptr<FileSystemStatCache> Cache) { - NextStatCache = std::move(Cache); - } - - /// Retrieve the next stat call cache in the chain. - FileSystemStatCache *getNextStatCache() { return NextStatCache.get(); } - - /// Retrieve the next stat call cache in the chain, transferring - /// ownership of this cache (and, transitively, all of the remaining caches) - /// to the caller. - std::unique_ptr<FileSystemStatCache> takeNextStatCache() { - return std::move(NextStatCache); - } - protected: // FIXME: The pointer here is a non-owning/optional reference to the // unique_ptr. Optional<unique_ptr<vfs::File>&> might be nicer, but @@ -111,17 +92,6 @@ protected: virtual LookupResult getStat(StringRef Path, FileData &Data, bool isFile, std::unique_ptr<llvm::vfs::File> *F, llvm::vfs::FileSystem &FS) = 0; - - LookupResult statChained(StringRef Path, FileData &Data, bool isFile, - std::unique_ptr<llvm::vfs::File> *F, - llvm::vfs::FileSystem &FS) { - if (FileSystemStatCache *Next = getNextStatCache()) - return Next->getStat(Path, Data, isFile, F, FS); - - // If we hit the end of the list of stat caches to try, just compute and - // return it without a cache. - return get(Path, Data, isFile, F, nullptr, FS) ? CacheMissing : CacheExists; - } }; /// A stat "cache" that can be used by FileManager to keep diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index be4491d512..49961856c9 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -207,6 +207,7 @@ LANGOPT(OpenMPCUDAForceFullRuntime , 1, 0, "Force to use full runtime in all con LANGOPT(OpenMPHostCXXExceptions , 1, 0, "C++ exceptions handling in the host code.") LANGOPT(OpenMPCUDANumSMs , 32, 0, "Number of SMs for CUDA devices.") LANGOPT(OpenMPCUDABlocksPerSM , 32, 0, "Number of blocks per SM for CUDA devices.") +LANGOPT(OpenMPOptimisticCollapse , 1, 0, "Use at most 32 bits to represent the collapsed loop nest counter.") LANGOPT(RenderScript , 1, 0, "RenderScript") LANGOPT(CUDAIsDevice , 1, 0, "compiling for CUDA device") @@ -263,6 +264,8 @@ ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility, "type symbol visibility") ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, "stack protector mode") +ENUM_LANGOPT(TrivialAutoVarInit, TrivialAutoVarInitKind, 2, TrivialAutoVarInitKind::Uninitialized, + "trivial automatic variable initialization") ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined, "signed integer overflow handling") diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 34f510f5ca..9cff7c5160 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -54,6 +54,11 @@ public: enum GCMode { NonGC, GCOnly, HybridGC }; enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq }; + // Automatic variables live on the stack, and when trivial they're usually + // uninitialized because it's undefined behavior to use them without + // initializing them. + enum class TrivialAutoVarInitKind { Uninitialized, Zero, Pattern }; + enum SignedOverflowBehaviorTy { // Default C standard behavior. SOB_Undefined, @@ -98,11 +103,14 @@ public: enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; + // Corresponds to _MSC_VER enum MSVCMajorVersion { - MSVC2010 = 16, - MSVC2012 = 17, - MSVC2013 = 18, - MSVC2015 = 19 + MSVC2010 = 1600, + MSVC2012 = 1700, + MSVC2013 = 1800, + MSVC2015 = 1900, + MSVC2017 = 1910, + MSVC2017_5 = 1912 }; /// Clang versions with different platform ABI conformance. @@ -271,7 +279,7 @@ public: } bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const { - return MSCompatibilityVersion >= MajorVersion * 10000000U; + return MSCompatibilityVersion >= MajorVersion * 100000U; } /// Reset all of the options that are not considered when building a diff --git a/include/clang/Basic/MSP430Target.def b/include/clang/Basic/MSP430Target.def new file mode 100644 index 0000000000..758113c5f5 --- /dev/null +++ b/include/clang/Basic/MSP430Target.def @@ -0,0 +1,247 @@ +//===--- MSP430Target.def - MSP430 Feature/Processor Database----*- 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 MSP430 devices and their features. +// +//===----------------------------------------------------------------------===// + +#ifndef MSP430_MCU_FEAT +#define MSP430_MCU_FEAT(NAME, HWMULT) MSP430_MCU(NAME) +#endif + +#ifndef MSP430_MCU +#define MSP430_MCU(NAME) +#endif + +MSP430_MCU("msp430c111") +MSP430_MCU("msp430c1111") +MSP430_MCU("msp430c112") +MSP430_MCU("msp430c1121") +MSP430_MCU("msp430c1331") +MSP430_MCU("msp430c1351") +MSP430_MCU("msp430e112") +MSP430_MCU("msp430f110") +MSP430_MCU("msp430f1101") +MSP430_MCU("msp430f1101a") +MSP430_MCU("msp430f1111") +MSP430_MCU("msp430f1111a") +MSP430_MCU("msp430f112") +MSP430_MCU("msp430f1121") +MSP430_MCU("msp430f1121a") +MSP430_MCU("msp430f1122") +MSP430_MCU("msp430f1132") +MSP430_MCU("msp430f122") +MSP430_MCU("msp430f1222") +MSP430_MCU("msp430f123") +MSP430_MCU("msp430f1232") +MSP430_MCU("msp430f133") +MSP430_MCU("msp430f135") +MSP430_MCU("msp430f155") +MSP430_MCU("msp430f156") +MSP430_MCU("msp430f157") +MSP430_MCU("msp430p112") +MSP430_MCU("msp430f2001") +MSP430_MCU("msp430f2011") +MSP430_MCU("msp430f2002") +MSP430_MCU("msp430f2012") +MSP430_MCU("msp430f2003") +MSP430_MCU("msp430f2013") +MSP430_MCU("msp430f2101") +MSP430_MCU("msp430f2111") +MSP430_MCU("msp430f2121") +MSP430_MCU("msp430f2131") +MSP430_MCU("msp430f2112") +MSP430_MCU("msp430f2122") +MSP430_MCU("msp430f2132") +MSP430_MCU("msp430f2232") +MSP430_MCU("msp430f2252") +MSP430_MCU("msp430f2272") +MSP430_MCU("msp430f2234") +MSP430_MCU("msp430f2254") +MSP430_MCU("msp430f2274") +MSP430_MCU("msp430g2211") +MSP430_MCU("msp430g2201") +MSP430_MCU("msp430g2111") +MSP430_MCU("msp430g2101") +MSP430_MCU("msp430g2001") +MSP430_MCU("msp430g2231") +MSP430_MCU("msp430g2221") +MSP430_MCU("msp430g2131") +MSP430_MCU("msp430g2121") +MSP430_MCU("msp430g2102") +MSP430_MCU("msp430g2202") +MSP430_MCU("msp430g2302") +MSP430_MCU("msp430g2402") +MSP430_MCU("msp430g2132") +MSP430_MCU("msp430g2232") +MSP430_MCU("msp430g2332") +MSP430_MCU("msp430g2432") +MSP430_MCU("msp430g2112") +MSP430_MCU("msp430g2212") +MSP430_MCU("msp430g2312") +MSP430_MCU("msp430g2412") +MSP430_MCU("msp430g2152") +MSP430_MCU("msp430g2252") +MSP430_MCU("msp430g2352") +MSP430_MCU("msp430g2452") +MSP430_MCU("msp430g2113") +MSP430_MCU("msp430g2213") +MSP430_MCU("msp430g2313") +MSP430_MCU("msp430g2413") +MSP430_MCU("msp430g2513") +MSP430_MCU("msp430g2153") +MSP430_MCU("msp430g2253") +MSP430_MCU("msp430g2353") +MSP430_MCU("msp430g2453") +MSP430_MCU("msp430g2553") +MSP430_MCU("msp430g2203") +MSP430_MCU("msp430g2303") +MSP430_MCU("msp430g2403") +MSP430_MCU("msp430g2233") +MSP430_MCU("msp430g2333") +MSP430_MCU("msp430g2433") +MSP430_MCU("msp430g2533") +MSP430_MCU("msp430tch5e") +MSP430_MCU("msp430g2444") +MSP430_MCU("msp430g2544") +MSP430_MCU("msp430g2744") +MSP430_MCU("msp430g2755") +MSP430_MCU("msp430g2855") +MSP430_MCU("msp430g2955") +MSP430_MCU("msp430g2230") +MSP430_MCU("msp430g2210") +MSP430_MCU("msp430c311s") +MSP430_MCU("msp430c312") +MSP430_MCU("msp430c313") +MSP430_MCU("msp430c314") +MSP430_MCU("msp430c315") +MSP430_MCU("msp430c323") +MSP430_MCU("msp430c325") +MSP430_MCU("msp430c412") +MSP430_MCU("msp430c413") +MSP430_MCU("msp430e313") +MSP430_MCU("msp430e315") +MSP430_MCU("msp430e325") +MSP430_MCU("msp430p313") +MSP430_MCU("msp430p315") +MSP430_MCU("msp430p315s") +MSP430_MCU("msp430p325") +MSP430_MCU("msp430f412") +MSP430_MCU("msp430f413") +MSP430_MCU("msp430f415") +MSP430_MCU("msp430f417") +MSP430_MCU("msp430f4132") +MSP430_MCU("msp430f4152") +MSP430_MCU("msp430f435") +MSP430_MCU("msp430f436") +MSP430_MCU("msp430f437") +MSP430_MCU("msp430f4351") +MSP430_MCU("msp430f4361") +MSP430_MCU("msp430f4371") +MSP430_MCU("msp430fe423") +MSP430_MCU("msp430fe425") +MSP430_MCU("msp430fe427") +MSP430_MCU("msp430fe423a") +MSP430_MCU("msp430fe425a") +MSP430_MCU("msp430fe427a") +MSP430_MCU("msp430fe4232") +MSP430_MCU("msp430fe4242") +MSP430_MCU("msp430fe4252") +MSP430_MCU("msp430fe4272") +MSP430_MCU("msp430f4250") +MSP430_MCU("msp430f4260") +MSP430_MCU("msp430f4270") +MSP430_MCU("msp430fg4250") +MSP430_MCU("msp430fg4260") +MSP430_MCU("msp430fg4270") +MSP430_MCU("msp430fw423") +MSP430_MCU("msp430fw425") +MSP430_MCU("msp430fw427") +MSP430_MCU("msp430fw428") +MSP430_MCU("msp430fw429") +MSP430_MCU("msp430fg437") +MSP430_MCU("msp430fg438") +MSP430_MCU("msp430fg439") +MSP430_MCU("msp430f438") +MSP430_MCU("msp430f439") +MSP430_MCU("msp430f477") +MSP430_MCU("msp430f478") +MSP430_MCU("msp430f479") +MSP430_MCU("msp430fg477") +MSP430_MCU("msp430fg478") +MSP430_MCU("msp430fg479") + +// With 16-bit hardware multiplier +MSP430_MCU_FEAT("msp430f147", "16bit") +MSP430_MCU_FEAT("msp430f148", "16bit") +MSP430_MCU_FEAT("msp430f149", "16bit") +MSP430_MCU_FEAT("msp430f1471", "16bit") +MSP430_MCU_FEAT("msp430f1481", "16bit") +MSP430_MCU_FEAT("msp430f1491", "16bit") +MSP430_MCU_FEAT("msp430f167", "16bit") +MSP430_MCU_FEAT("msp430f168", "16bit") +MSP430_MCU_FEAT("msp430f169", "16bit") +MSP430_MCU_FEAT("msp430f1610", "16bit") +MSP430_MCU_FEAT("msp430f1611", "16bit") +MSP430_MCU_FEAT("msp430f1612", "16bit") +MSP430_MCU_FEAT("msp430c336", "16bit") +MSP430_MCU_FEAT("msp430c337", "16bit") +MSP430_MCU_FEAT("msp430e337", "16bit") +MSP430_MCU_FEAT("msp430p337", "16bit") +MSP430_MCU_FEAT("msp430f423", "16bit") +MSP430_MCU_FEAT("msp430f425", "16bit") +MSP430_MCU_FEAT("msp430f427", "16bit") +MSP430_MCU_FEAT("msp430f423a", "16bit") +MSP430_MCU_FEAT("msp430f425a", "16bit") +MSP430_MCU_FEAT("msp430f427a", "16bit") +MSP430_MCU_FEAT("msp430f4481", "16bit") +MSP430_MCU_FEAT("msp430f4491", "16bit") +MSP430_MCU_FEAT("msp430f447", "16bit") +MSP430_MCU_FEAT("msp430f448", "16bit") +MSP430_MCU_FEAT("msp430f449", "16bit") +MSP430_MCU_FEAT("msp430f2330", "16bit") +MSP430_MCU_FEAT("msp430f2350", "16bit") +MSP430_MCU_FEAT("msp430f2370", "16bit") +MSP430_MCU_FEAT("msp430f233", "16bit") +MSP430_MCU_FEAT("msp430f235", "16bit") +MSP430_MCU_FEAT("msp430f247", "16bit") +MSP430_MCU_FEAT("msp430f248", "16bit") +MSP430_MCU_FEAT("msp430f249", "16bit") +MSP430_MCU_FEAT("msp430f2410", "16bit") +MSP430_MCU_FEAT("msp430f2471", "16bit") +MSP430_MCU_FEAT("msp430f2481", "16bit") +MSP430_MCU_FEAT("msp430f2491", "16bit") +MSP430_MCU_FEAT("msp430i2020", "16bit") +MSP430_MCU_FEAT("msp430i2021", "16bit") +MSP430_MCU_FEAT("msp430i2030", "16bit") +MSP430_MCU_FEAT("msp430i2031", "16bit") +MSP430_MCU_FEAT("msp430i2040", "16bit") +MSP430_MCU_FEAT("msp430i2041", "16bit") +MSP430_MCU_FEAT("msp430afe221", "16bit") +MSP430_MCU_FEAT("msp430afe231", "16bit") +MSP430_MCU_FEAT("msp430afe251", "16bit") +MSP430_MCU_FEAT("msp430afe222", "16bit") +MSP430_MCU_FEAT("msp430afe232", "16bit") +MSP430_MCU_FEAT("msp430afe252", "16bit") +MSP430_MCU_FEAT("msp430afe223", "16bit") +MSP430_MCU_FEAT("msp430afe233", "16bit") +MSP430_MCU_FEAT("msp430afe253", "16bit") + +// With 32 Bit Hardware Multiplier +MSP430_MCU_FEAT("msp430f4783", "32bit") +MSP430_MCU_FEAT("msp430f4793", "32bit") +MSP430_MCU_FEAT("msp430f4784", "32bit") +MSP430_MCU_FEAT("msp430f4794", "32bit") + +// Generic MSUs +MSP430_MCU("msp430") +MSP430_MCU("msp430i2xxgeneric") + +#undef MSP430_MCU +#undef MSP430_MCU_FEAT diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index f8b4826d3d..fcfbe56b49 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -173,6 +173,43 @@ public: llvm_unreachable("bad kind"); } + /// Does this runtime provide ARC entrypoints that are likely to be faster + /// than an ordinary message send of the appropriate selector? + /// + /// The ARC entrypoints are guaranteed to be equivalent to just sending the + /// corresponding message. If the entrypoint is implemented naively as just a + /// message send, using it is a trade-off: it sacrifices a few cycles of + /// overhead to save a small amount of code. However, it's possible for + /// runtimes to detect and special-case classes that use "standard" + /// retain/release behavior; if that's dynamically a large proportion of all + /// retained objects, using the entrypoint will also be faster than using a + /// message send. + /// + /// When this method returns true, Clang will turn non-super message sends of + /// certain selectors into calls to the correspond entrypoint: + /// retain => objc_retain + /// release => objc_release + /// autorelease => objc_autorelease + bool shouldUseARCFunctionsForRetainRelease() const { + switch (getKind()) { + case FragileMacOSX: + return false; + case MacOSX: + return getVersion() >= VersionTuple(10, 10); + case iOS: + return getVersion() >= VersionTuple(8); + case WatchOS: + return true; + case GCC: + return false; + case GNUstep: + return false; + case ObjFW: + return false; + } + llvm_unreachable("bad kind"); + } + /// Does this runtime provide entrypoints that are likely to be faster /// than an ordinary message send of the "alloc" selector? /// diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index eb9881115c..f86721b1b0 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -120,6 +120,9 @@ #ifndef OPENMP_MAP_KIND #define OPENMP_MAP_KIND(Name) #endif +#ifndef OPENMP_MAP_MODIFIER_KIND +#define OPENMP_MAP_MODIFIER_KIND(Name) +#endif #ifndef OPENMP_DIST_SCHEDULE_KIND #define OPENMP_DIST_SCHEDULE_KIND(Name) #endif @@ -559,14 +562,17 @@ OPENMP_ORDERED_CLAUSE(threads) OPENMP_ORDERED_CLAUSE(simd) OPENMP_ORDERED_CLAUSE(depend) -// Map types and map type modifier for 'map' clause. +// Map types for 'map' clause. OPENMP_MAP_KIND(alloc) OPENMP_MAP_KIND(to) OPENMP_MAP_KIND(from) OPENMP_MAP_KIND(tofrom) OPENMP_MAP_KIND(delete) OPENMP_MAP_KIND(release) -OPENMP_MAP_KIND(always) + +// Map-type-modifiers for 'map' clause. +OPENMP_MAP_MODIFIER_KIND(always) +OPENMP_MAP_MODIFIER_KIND(close) // Clauses allowed for OpenMP directive 'taskloop'. OPENMP_TASKLOOP_CLAUSE(if) @@ -919,6 +925,7 @@ OPENMP_TASKGROUP_CLAUSE(task_reduction) #undef OPENMP_FOR_CLAUSE #undef OPENMP_FOR_SIMD_CLAUSE #undef OPENMP_MAP_KIND +#undef OPENMP_MAP_MODIFIER_KIND #undef OPENMP_DISTRIBUTE_CLAUSE #undef OPENMP_DIST_SCHEDULE_KIND #undef OPENMP_DEFAULTMAP_KIND diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h index b0fab5ab11..3e03a48cf6 100644 --- a/include/clang/Basic/OpenMPKinds.h +++ b/include/clang/Basic/OpenMPKinds.h @@ -96,6 +96,15 @@ enum OpenMPMapClauseKind { OMPC_MAP_unknown }; +/// OpenMP modifier kind for 'map' clause. +enum OpenMPMapModifierKind { + OMPC_MAP_MODIFIER_unknown = OMPC_MAP_unknown, +#define OPENMP_MAP_MODIFIER_KIND(Name) \ + OMPC_MAP_MODIFIER_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_MAP_MODIFIER_last +}; + /// OpenMP attributes for 'dist_schedule' clause. enum OpenMPDistScheduleClauseKind { #define OPENMP_DIST_SCHEDULE_KIND(Name) OMPC_DIST_SCHEDULE_##Name, diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h index 2ecbde8215..fe9e76a1e3 100644 --- a/include/clang/Basic/Sanitizers.h +++ b/include/clang/Basic/Sanitizers.h @@ -66,7 +66,7 @@ struct SanitizerSet { /// Disable the sanitizers specified in \p K. void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; } - /// Returns true if at least one sanitizer is enabled. + /// Returns true if no sanitizers are enabled. bool empty() const { return Mask == 0; } /// Bitmask of enabled sanitizers. diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h index 75a3811007..ab4b1c43f7 100644 --- a/include/clang/Basic/TargetBuiltins.h +++ b/include/clang/Basic/TargetBuiltins.h @@ -150,16 +150,6 @@ namespace clang { }; } - /// Nios2 builtins - namespace Nios2 { - enum { - LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, -#define BUILTIN(ID, TYPE, ATTRS) BI##ID, -#include "clang/Basic/BuiltinsNios2.def" - LastTSBuiltin - }; - } - /// MIPS builtins namespace Mips { enum { diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 4a7254e02c..786b1c251c 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -1321,6 +1321,12 @@ public: return None; } + /// \returns The version of the SDK which was used during the compilation if + /// one was specified, or an empty version otherwise. + const llvm::VersionTuple &getSDKVersion() const { + return getTargetOpts().SDKVersion; + } + /// Check the target is valid after it is fully initialized. virtual bool validateTarget(DiagnosticsEngine &Diags) const { return true; diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index 7559e3169e..fcccc5331a 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -15,10 +15,11 @@ #ifndef LLVM_CLANG_BASIC_TARGETOPTIONS_H #define LLVM_CLANG_BASIC_TARGETOPTIONS_H -#include <string> -#include <vector> #include "clang/Basic/OpenCLOptions.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Target/TargetOptions.h" +#include <string> +#include <vector> namespace clang { @@ -73,6 +74,9 @@ public: // "default" for the case when the user has not explicitly specified a // code model. std::string CodeModel; + + /// The version of the SDK which was used during the compilation. + llvm::VersionTuple SDKVersion; }; } // end namespace clang diff --git a/include/clang/CrossTU/CrossTranslationUnit.h b/include/clang/CrossTU/CrossTranslationUnit.h index b5371a6de7..52e3ae2749 100644 --- a/include/clang/CrossTU/CrossTranslationUnit.h +++ b/include/clang/CrossTU/CrossTranslationUnit.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H #define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H +#include "clang/AST/ASTImporterLookupTable.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" @@ -89,11 +90,11 @@ std::string createCrossTUIndexString(const llvm::StringMap<std::string> &Index); /// This class is used for tools that requires cross translation /// unit capability. /// -/// This class can load function definitions from external AST files. +/// This class can load definitions from external AST files. /// The loaded definition will be merged back to the original AST using the /// AST Importer. /// In order to use this class, an index file is required that describes -/// the locations of the AST files for each function definition. +/// the locations of the AST files for each definition. /// /// Note that this class also implements caching. class CrossTranslationUnitContext { @@ -129,8 +130,9 @@ public: /// \p IndexName. In case the declaration is found in the index the /// corresponding AST file will be loaded. /// - /// \return Returns an ASTUnit that contains the definition of the looked up - /// function. + /// \return Returns a pointer to the ASTUnit that contains the definition of + /// the looked up function or an Error. + /// The returned pointer is never a nullptr. /// /// Note that the AST files should also be in the \p CrossTUDir. llvm::Expected<ASTUnit *> loadExternalAST(StringRef LookupName, @@ -152,6 +154,7 @@ public: void emitCrossTUDiagnostics(const IndexError &IE); private: + void lazyInitLookupTable(TranslationUnitDecl *ToTU); ASTImporter &getOrCreateASTImporter(ASTContext &From); const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC, StringRef LookupFnName); @@ -163,6 +166,7 @@ private: ASTUnitImporterMap; CompilerInstance &CI; ASTContext &Context; + std::unique_ptr<ASTImporterLookupTable> LookupTable; }; } // namespace cross_tu diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 9d2d2df7d2..07c7688406 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -27,6 +27,8 @@ def triple : Separate<["-"], "triple">, HelpText<"Specify target triple (e.g. i686-apple-darwin9)">; def target_abi : Separate<["-"], "target-abi">, HelpText<"Target a particular ABI type">; +def target_sdk_version_EQ : Joined<["-"], "target-sdk-version=">, + HelpText<"The version of target SDK used for compilation">; } @@ -106,7 +108,7 @@ def analyzer_checker : Separate<["-"], "analyzer-checker">, ValuesCode<[{ const char *Values = #define GET_CHECKERS - #define CHECKER(FULLNAME, CLASS, HT) FULLNAME "," + #define CHECKER(FULLNAME, CLASS, HT, DOC_URI) FULLNAME "," #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef GET_CHECKERS #define GET_PACKAGES @@ -161,6 +163,8 @@ let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; def debug_info_macro : Flag<["-"], "debug-info-macro">, HelpText<"Emit macro debug information">; +def default_function_attr : Separate<["-"], "default-function-attr">, + HelpText<"Apply given attribute to all functions">; def dwarf_version_EQ : Joined<["-"], "dwarf-version=">; def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">; def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">, diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index 3d64aa07ec..3e0dc2db7d 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -116,14 +116,14 @@ def _SLASH_J : CLFlag<"J">, HelpText<"Make char type unsigned">, // The _SLASH_O option handles all the /O flags, but we also provide separate // aliased options to provide separate help messages. def _SLASH_O : CLJoined<"O">, - HelpText<"Set multiple /O flags at once; e.g. '/O2y-' is the same as '/O2 /y-'">, + HelpText<"Set multiple /O flags at once; e.g. '/O2y-' for '/O2 /Oy-'">, MetaVarName<"<flags>">; // FIXME: Not sure why we have -O0 here; MSVC doesn't support that. def : CLFlag<"O0">, Alias<O0>, HelpText<"Disable optimization">; def : CLFlag<"O1">, Alias<_SLASH_O>, AliasArgs<["1"]>, - HelpText<"Optimize for size (equivalent to /Og /Os /Oy /Ob2 /GF /Gy)">; + HelpText<"Optimize for size (same as /Og /Os /Oy /Ob2 /GF /Gy)">; def : CLFlag<"O2">, Alias<_SLASH_O>, AliasArgs<["2"]>, - HelpText<"Optimize for speed (equivalent to /Og /Oi /Ot /Oy /Ob2 /GF /Gy)">; + HelpText<"Optimize for speed (same as /Og /Oi /Ot /Oy /Ob2 /GF /Gy)">; def : CLFlag<"Ob0">, Alias<_SLASH_O>, AliasArgs<["b0"]>, HelpText<"Disable function inlining">; def : CLFlag<"Ob1">, Alias<_SLASH_O>, AliasArgs<["b1"]>, @@ -143,7 +143,7 @@ def : CLFlag<"Os">, Alias<_SLASH_O>, AliasArgs<["s"]>, def : CLFlag<"Ot">, Alias<_SLASH_O>, AliasArgs<["t"]>, HelpText<"Optimize for speed">; def : CLFlag<"Ox">, Alias<_SLASH_O>, AliasArgs<["x"]>, - HelpText<"Deprecated (equivalent to /Og /Oi /Ot /Oy /Ob2); use /O2 instead">; + HelpText<"Deprecated (same as /Og /Oi /Ot /Oy /Ob2); use /O2 instead">; def : CLFlag<"Oy">, Alias<_SLASH_O>, AliasArgs<["y"]>, HelpText<"Enable frame pointer omission (x86 only)">; def : CLFlag<"Oy-">, Alias<_SLASH_O>, AliasArgs<["y-"]>, @@ -207,6 +207,12 @@ def _SLASH_Zc_sizedDealloc : CLFlag<"Zc:sizedDealloc">, def _SLASH_Zc_sizedDealloc_ : CLFlag<"Zc:sizedDealloc-">, HelpText<"Disable C++14 sized global deallocation functions">, Alias<fno_sized_deallocation>; +def _SLASH_Zc_alignedNew : CLFlag<"Zc:alignedNew">, + HelpText<"Enable C++17 aligned allocation functions">, + Alias<faligned_allocation>; +def _SLASH_Zc_alignedNew_ : CLFlag<"Zc:alignedNew-">, + HelpText<"Disable C++17 aligned allocation functions">, + Alias<fno_aligned_allocation>; def _SLASH_Zc_strictStrings : CLFlag<"Zc:strictStrings">, HelpText<"Treat string literals as const">, Alias<W_Joined>, AliasArgs<["error=c++11-compat-deprecated-writable-strings"]>; diff --git a/include/clang/Driver/DarwinSDKInfo.h b/include/clang/Driver/DarwinSDKInfo.h new file mode 100644 index 0000000000..4ffb02fea3 --- /dev/null +++ b/include/clang/Driver/DarwinSDKInfo.h @@ -0,0 +1,42 @@ +//===--- DarwinSDKInfo.h - SDK Information parser for darwin ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DRIVER_DARWIN_SDK_INFO_H +#define LLVM_CLANG_DRIVER_DARWIN_SDK_INFO_H + +#include "clang/Basic/LLVM.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/VersionTuple.h" +#include "llvm/Support/VirtualFileSystem.h" + +namespace clang { +namespace driver { + +/// The information about the darwin SDK that was used during this compilation. +class DarwinSDKInfo { +public: + DarwinSDKInfo(llvm::VersionTuple Version) : Version(Version) {} + + const llvm::VersionTuple &getVersion() const { return Version; } + +private: + llvm::VersionTuple Version; +}; + +/// Parse the SDK information from the SDKSettings.json file. +/// +/// \returns an error if the SDKSettings.json file is invalid, None if the +/// SDK has no SDKSettings.json, or a valid \c DarwinSDKInfo otherwise. +Expected<Optional<DarwinSDKInfo>> parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, + StringRef SDKRootPath); + +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_DRIVER_DARWIN_SDK_INFO_H diff --git a/include/clang/Driver/Distro.h b/include/clang/Driver/Distro.h index 3cf7048298..5651ebb6d4 100644 --- a/include/clang/Driver/Distro.h +++ b/include/clang/Driver/Distro.h @@ -39,6 +39,7 @@ public: RHEL6, RHEL7, Fedora, + Gentoo, OpenSUSE, UbuntuHardy, UbuntuIntrepid, @@ -123,6 +124,10 @@ public: return DistroVal == AlpineLinux; } + bool IsGentoo() const { + return DistroVal == Gentoo; + } + /// @} }; diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 31c17272ca..494336d672 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -505,6 +505,10 @@ public: /// GCC goes to extra lengths here to be a bit more robust. std::string GetTemporaryPath(StringRef Prefix, StringRef Suffix) const; + /// GetTemporaryDirectory - Return the pathname of a temporary directory to + /// use as part of compilation; the directory will have the given prefix. + std::string GetTemporaryDirectory(StringRef Prefix) const; + /// Return the pathname of the pch file in clang-cl mode. std::string GetClPchPath(Compilation &C, StringRef BaseName) const; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index acf82c5ab2..f02a7190f5 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -998,6 +998,10 @@ def fno_sanitize_address_use_odr_indicator : Flag<["-"], "fno-sanitize-address-use-odr-indicator">, Group<f_clang_Group>, HelpText<"Disable ODR indicator globals">; +def fsanitize_hwaddress_abi_EQ + : Joined<["-"], "fsanitize-hwaddress-abi=">, + Group<f_clang_Group>, + HelpText<"Select the HWAddressSanitizer ABI to target (interceptor or platform, default interceptor)">; def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>; def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, Flags<[CoreOption, DriverOption]>, @@ -1570,6 +1574,10 @@ def fopenmp_cuda_number_of_sm_EQ : Joined<["-"], "fopenmp-cuda-number-of-sm=">, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; def fopenmp_cuda_blocks_per_sm_EQ : Joined<["-"], "fopenmp-cuda-blocks-per-sm=">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; +def fopenmp_optimistic_collapse : Flag<["-"], "fopenmp-optimistic-collapse">, Group<f_Group>, + Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; +def fno_openmp_optimistic_collapse : Flag<["-"], "fno-openmp-optimistic-collapse">, Group<f_Group>, + Flags<[NoArgumentUnused, HelpHidden]>; def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>; def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>; def fno_escaping_block_tail_calls : Flag<["-"], "fno-escaping-block-tail-calls">, Group<f_Group>, Flags<[CC1Option]>; @@ -1639,11 +1647,24 @@ def fno_signed_char : Flag<["-"], "fno-signed-char">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Char is unsigned">; def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>; def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>, - HelpText<"Force the usage of stack protectors for all functions">; + HelpText<"Enable stack protectors for all functions">; def fstack_protector_strong : Flag<["-"], "fstack-protector-strong">, Group<f_Group>, - HelpText<"Use a strong heuristic to apply stack protectors to functions">; + HelpText<"Enable stack protectors for some functions vulnerable to stack smashing. " + "Compared to -fstack-protector, this uses a stronger heuristic " + "that includes functions containing arrays of any size (and any type), " + "as well as any calls to alloca or the taking of an address from a local variable">; def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>, - HelpText<"Enable stack protectors for functions potentially vulnerable to stack smashing">; + HelpText<"Enable stack protectors for some functions vulnerable to stack smashing. " + "This uses a loose heuristic which considers functions vulnerable " + "if they contain a char (or 8bit integer) array or constant sized calls to " + "alloca, which are of greater size than ssp-buffer-size (default: 8 bytes). " + "All variable sized calls to alloca are considered vulnerable">; +def ftrivial_auto_var_init : Joined<["-"], "ftrivial-auto-var-init=">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Initialize trivial automatic stack variables: uninitialized (default)" + " | pattern">, Values<"uninitialized,pattern">; +def enable_trivial_var_init_zero : Joined<["-"], "enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang">, + Flags<[CC1Option]>, + HelpText<"Trivial automatic variable initialization to zero is only here for benchmarks, it'll eventually be removed, and I'm OK with that because I'm only using it to benchmark">; def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>, Flags<[CoreOption]>, HelpText<"Emit full debug info for all types used by the program">; def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>, Flags<[CoreOption]>, @@ -1755,6 +1776,11 @@ def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Grou HelpText<"Enables whole-program vtable optimization. Requires -flto">; def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>, Flags<[CoreOption]>; +def fsplit_lto_unit : Flag<["-"], "fsplit-lto-unit">, Group<f_Group>, + Flags<[CoreOption, CC1Option]>, + HelpText<"Enables splitting of the LTO unit.">; +def fno_split_lto_unit : Flag<["-"], "fno-split-lto-unit">, Group<f_Group>, + Flags<[CoreOption]>; def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Emits more virtual tables to improve devirtualization">; @@ -2009,6 +2035,7 @@ def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>, Values<"soft,s def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>; def mfpu_EQ : Joined<["-"], "mfpu=">, Group<m_Group>; def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>; +def mhwmult_EQ : Joined<["-"], "mhwmult=">, Group<m_Group>; def mglobal_merge : Flag<["-"], "mglobal-merge">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Enable merging of globals">; def mhard_float : Flag<["-"], "mhard-float">, Group<m_Group>; @@ -2120,6 +2147,8 @@ def mbranch_protection_EQ : Joined<["-"], "mbranch-protection=">, HelpText<"Enforce targets of indirect branches and function returns">; def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>; +def munimplemented_simd128 : Flag<["-"], "munimplemented-simd128">, Group<m_wasm_Features_Group>; +def mno_unimplemented_simd128 : Flag<["-"], "mno-unimplemented-simd128">, Group<m_wasm_Features_Group>; def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>; def mnontrapping_fptoint : Flag<["-"], "mnontrapping-fptoint">, Group<m_wasm_Features_Group>; def mno_nontrapping_fptoint : Flag<["-"], "mno-nontrapping-fptoint">, Group<m_wasm_Features_Group>; diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index 763a187d71..e590a49dee 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -39,6 +39,7 @@ class SanitizerArgs { bool AsanPoisonCustomArrayCookie = false; bool AsanGlobalsDeadStripping = false; bool AsanUseOdrIndicator = false; + std::string HwasanAbi; bool LinkCXXRuntimes = false; bool NeedPIE = false; bool SafeStackRuntime = false; @@ -80,8 +81,10 @@ class SanitizerArgs { bool requiresPIE() const; bool needsUnwindTables() const; + bool needsLTO() const; bool linkCXXRuntimes() const { return LinkCXXRuntimes; } bool hasCrossDsoCfi() const { return CfiCrossDso; } + bool hasAnySanitizer() const { return !Sanitizers.empty(); } void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const; }; diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 43a82a7b43..d5f75b8271 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -12,8 +12,8 @@ #include "clang/Basic/DebugInfoOptions.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/Sanitizers.h" -#include "clang/Basic/DebugInfoOptions.h" #include "clang/Driver/Action.h" #include "clang/Driver/Multilib.h" #include "clang/Driver/Types.h" @@ -350,6 +350,12 @@ public: return 0; } + /// Get the default trivial automatic variable initialization. + virtual LangOptions::TrivialAutoVarInitKind + GetDefaultTrivialAutoVarInit() const { + return LangOptions::TrivialAutoVarInitKind::Uninitialized; + } + /// GetDefaultLinker - Get the default linker to use. virtual const char *getDefaultLinker() const { return "ld"; } diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 4daa1dd817..a38c8d7819 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -45,6 +45,8 @@ class SourceManager; /// A mechanism to observe the actions of the module map parser as it /// reads module map files. class ModuleMapCallbacks { + virtual void anchor(); + public: virtual ~ModuleMapCallbacks() = default; diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index 44d79d9b62..027dd3ac5d 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H #define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/PPCallbacks.h" diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 09e81d22ae..438ff0e2ed 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_PARSE_PARSER_H #define LLVM_CLANG_PARSE_PARSER_H +#include "clang/AST/OpenMPClause.h" #include "clang/AST/Availability.h" #include "clang/Basic/BitmaskEnum.h" #include "clang/Basic/OpenMPKinds.h" @@ -359,6 +360,11 @@ class Parser : public CodeCompletionHandler { /// just a regular sub-expression. SourceLocation ExprStatementTokLoc; + /// Tests whether an expression value is discarded based on token lookahead. + /// It will return true if the lexer is currently processing the }) + /// terminating a GNU statement expression and false otherwise. + bool isExprValueDiscarded(); + public: Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies); ~Parser() override; @@ -2876,7 +2882,10 @@ public: DeclarationNameInfo ReductionId; OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; OpenMPLinearClauseKind LinKind = OMPC_LINEAR_val; - OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; + SmallVector<OpenMPMapModifierKind, OMPMapClause::NumberOfModifiers> + MapTypeModifiers; + SmallVector<SourceLocation, OMPMapClause::NumberOfModifiers> + MapTypeModifiersLoc; OpenMPMapClauseKind MapType = OMPC_MAP_unknown; bool IsMapTypeImplicit = false; SourceLocation DepLinMapLoc; diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index b667e077f5..8d6f0bc914 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -593,6 +593,18 @@ public: FS_noreturnLoc = SourceLocation(); } + /// This method calls the passed in handler on each CVRU qual being + /// set. + /// Handle - a handler to be invoked. + void forEachCVRUQualifier( + llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle); + + /// This method calls the passed in handler on each qual being + /// set. + /// Handle - a handler to be invoked. + void forEachQualifier( + llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle); + /// Return true if any type-specifier has been found. bool hasTypeSpecifier() const { return getTypeSpecType() != DeclSpec::TST_unspecified || @@ -683,6 +695,8 @@ public: ExprRep = Rep; } + bool SetTypeQual(TQ T, SourceLocation Loc); + bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const LangOptions &Lang); @@ -1250,10 +1264,6 @@ struct DeclaratorChunk { /// Otherwise, it's an rvalue reference. unsigned RefQualifierIsLValueRef : 1; - /// The type qualifiers: const/volatile/restrict/__unaligned - /// The qualifier bitmask values are the same as in QualType. - unsigned TypeQuals : 4; - /// ExceptionSpecType - An ExceptionSpecificationType value. unsigned ExceptionSpecType : 4; @@ -1287,21 +1297,6 @@ struct DeclaratorChunk { /// If this is an invalid location, there is no ref-qualifier. unsigned RefQualifierLoc; - /// The location of the const-qualifier, if any. - /// - /// If this is an invalid location, there is no const-qualifier. - unsigned ConstQualifierLoc; - - /// The location of the volatile-qualifier, if any. - /// - /// If this is an invalid location, there is no volatile-qualifier. - unsigned VolatileQualifierLoc; - - /// The location of the restrict-qualifier, if any. - /// - /// If this is an invalid location, there is no restrict-qualifier. - unsigned RestrictQualifierLoc; - /// The location of the 'mutable' qualifer in a lambda-declarator, if /// any. unsigned MutableLoc; @@ -1317,6 +1312,12 @@ struct DeclaratorChunk { /// there are no parameters specified. ParamInfo *Params; + /// DeclSpec for the function with the qualifier related info. + DeclSpec *MethodQualifiers; + + /// AtttibuteFactory for the MethodQualifiers. + AttributeFactory *QualAttrFactory; + union { /// Pointer to a new[]'d array of TypeAndRange objects that /// contain the types in the function's dynamic exception specification @@ -1356,6 +1357,8 @@ struct DeclaratorChunk { void destroy() { freeParams(); + delete QualAttrFactory; + delete MethodQualifiers; switch (getExceptionSpecType()) { default: break; @@ -1372,6 +1375,14 @@ struct DeclaratorChunk { } } + DeclSpec &getOrCreateMethodQualifiers() { + if (!MethodQualifiers) { + QualAttrFactory = new AttributeFactory(); + MethodQualifiers = new DeclSpec(*QualAttrFactory); + } + return *MethodQualifiers; + } + /// isKNRPrototype - Return true if this is a K&R style identifier list, /// like "void foo(a,b,c)". In a function definition, this will be followed /// by the parameter type definitions. @@ -1406,19 +1417,22 @@ struct DeclaratorChunk { return SourceLocation::getFromRawEncoding(RefQualifierLoc); } - /// Retrieve the location of the 'const' qualifier, if any. + /// Retrieve the location of the 'const' qualifier. SourceLocation getConstQualifierLoc() const { - return SourceLocation::getFromRawEncoding(ConstQualifierLoc); + assert(MethodQualifiers); + return MethodQualifiers->getConstSpecLoc(); } - /// Retrieve the location of the 'volatile' qualifier, if any. + /// Retrieve the location of the 'volatile' qualifier. SourceLocation getVolatileQualifierLoc() const { - return SourceLocation::getFromRawEncoding(VolatileQualifierLoc); + assert(MethodQualifiers); + return MethodQualifiers->getVolatileSpecLoc(); } - /// Retrieve the location of the 'restrict' qualifier, if any. + /// Retrieve the location of the 'restrict' qualifier. SourceLocation getRestrictQualifierLoc() const { - return SourceLocation::getFromRawEncoding(RestrictQualifierLoc); + assert(MethodQualifiers); + return MethodQualifiers->getRestrictSpecLoc(); } /// Retrieve the location of the 'mutable' qualifier, if any. @@ -1434,6 +1448,12 @@ struct DeclaratorChunk { /// qualifier. bool hasMutableQualifier() const { return getMutableLoc().isValid(); } + /// Determine whether this method has qualifiers. + bool hasMethodTypeQualifiers() const { + return MethodQualifiers && (MethodQualifiers->getTypeQualifiers() || + MethodQualifiers->getAttributes().size()); + } + /// Get the type of exception specification this function has. ExceptionSpecificationType getExceptionSpecType() const { return static_cast<ExceptionSpecificationType>(ExceptionSpecType); @@ -1574,12 +1594,8 @@ struct DeclaratorChunk { ParamInfo *Params, unsigned NumParams, SourceLocation EllipsisLoc, SourceLocation RParenLoc, - unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, - SourceLocation ConstQualifierLoc, - SourceLocation VolatileQualifierLoc, - SourceLocation RestrictQualifierLoc, SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, SourceRange ESpecRange, @@ -1593,7 +1609,8 @@ struct DeclaratorChunk { SourceLocation LocalRangeEnd, Declarator &TheDeclarator, TypeResult TrailingReturnType = - TypeResult()); + TypeResult(), + DeclSpec *MethodQualifiers = nullptr); /// Return a DeclaratorChunk for a block. static DeclaratorChunk getBlockPointer(unsigned TypeQuals, diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index 11fa036212..9d9ab0514f 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_SEMA_SCOPE_H #define LLVM_CLANG_SEMA_SCOPE_H +#include "clang/AST/Decl.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 4ddbf6caec..e5b7465820 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -307,6 +307,10 @@ class Sema { } bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New); + void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem, + QualType ResultTy, + ArrayRef<QualType> Args); + public: typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy; typedef OpaquePtr<TemplateName> TemplateTy; @@ -503,6 +507,8 @@ public: struct PragmaAttributeGroup { /// The location of the push attribute. SourceLocation Loc; + /// The namespace of this push group. + const IdentifierInfo *Namespace; SmallVector<PragmaAttributeEntry, 2> Entries; }; @@ -1363,6 +1369,7 @@ public: void PopCompoundScope(); sema::CompoundScopeInfo &getCurCompoundScope() const; + bool isCurCompoundStmtAStmtExpr() const; bool hasAnyUnrecoverableErrorsInThisFunction() const; @@ -1957,7 +1964,7 @@ public: bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); void CheckVariableDeclarationType(VarDecl *NewVD); bool DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, - Expr *Init); + Expr *&Init); void CheckCompleteVariableDeclaration(VarDecl *VD); void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD); void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D); @@ -3683,16 +3690,17 @@ public: return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); } FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { - return FullExprArg(ActOnFinishFullExpr(Arg, CC).get()); + return FullExprArg( + ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get()); } FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) { ExprResult FE = - ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), - /*DiscardedValue*/ true); + ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), + /*DiscardedValue*/ true); return FullExprArg(FE.get()); } - StmtResult ActOnExprStmt(ExprResult Arg); + StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true); StmtResult ActOnExprStmtError(); StmtResult ActOnNullStmt(SourceLocation SemiLoc, @@ -4815,7 +4823,7 @@ public: ImplicitExceptionSpecification ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD); - /// Determine what sort of exception specification a defautled + /// Determine what sort of exception specification a defaulted /// copy assignment operator of a class will have, and whether the /// parameter will be const. ImplicitExceptionSpecification @@ -5200,6 +5208,15 @@ public: SourceRange DirectInitRange, Expr *Initializer); + /// Determine whether \p FD is an aligned allocation or deallocation + /// function that is unavailable. + bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const; + + /// Produce diagnostics if \p FD is an aligned allocation or deallocation + /// function that is unavailable. + void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, + SourceLocation Loc); + bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R); @@ -5329,13 +5346,12 @@ public: CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference); - ExprResult ActOnFinishFullExpr(Expr *Expr) { - return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() - : SourceLocation()); + ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) { + return ActOnFinishFullExpr( + Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue); } ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC, - bool DiscardedValue = false, - bool IsConstexpr = false); + bool DiscardedValue, bool IsConstexpr = false); StmtResult ActOnFinishFullStmt(Stmt *Stmt); // Marks SS invalid if it represents an incomplete type. @@ -6344,9 +6360,9 @@ public: const TemplateArgumentListInfo &ExplicitTemplateArgs, LookupResult &Previous); - bool CheckFunctionTemplateSpecialization(FunctionDecl *FD, - TemplateArgumentListInfo *ExplicitTemplateArgs, - LookupResult &Previous); + bool CheckFunctionTemplateSpecialization( + FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs, + LookupResult &Previous, bool QualifiedFriend = false); bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous); @@ -7083,7 +7099,7 @@ public: QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name, QualType Type, TypeSourceInfo *TSI, SourceRange Range, bool DirectInit, - Expr *Init); + Expr *&Init); TypeLoc getReturnTypeLoc(FunctionDecl *FD) const; @@ -8494,10 +8510,12 @@ public: void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute, SourceLocation PragmaLoc, attr::ParsedSubjectMatchRuleSet Rules); - void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc); + void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc, + const IdentifierInfo *Namespace); /// Called on well-formed '\#pragma clang attribute pop'. - void ActOnPragmaAttributePop(SourceLocation PragmaLoc); + void ActOnPragmaAttributePop(SourceLocation PragmaLoc, + const IdentifierInfo *Namespace); /// Adds the attributes that have been specified using the /// '\#pragma clang attribute push' directives to the given declaration. @@ -9233,7 +9251,9 @@ public: SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind, - OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier, + OpenMPLinearClauseKind LinKind, + ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, + ArrayRef<SourceLocation> MapTypeModifiersLoc, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation DepLinMapLoc); /// Called on well-formed 'private' clause. @@ -9317,7 +9337,8 @@ public: SourceLocation EndLoc); /// Called on well-formed 'map' clause. OMPClause * - ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier, + ActOnOpenMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, + ArrayRef<SourceLocation> MapTypeModifiersLoc, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, @@ -9839,21 +9860,20 @@ public: /// \param Method - May be null. /// \param [out] ReturnType - The return type of the send. /// \return true iff there were any incompatible types. - bool CheckMessageArgumentTypes(QualType ReceiverType, + bool CheckMessageArgumentTypes(const Expr *Receiver, QualType ReceiverType, MultiExprArg Args, Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method, bool isClassMessage, - bool isSuperMessage, - SourceLocation lbrac, SourceLocation rbrac, - SourceRange RecRange, + bool isSuperMessage, SourceLocation lbrac, + SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType, ExprValueKind &VK); /// Determine the result of a message send expression based on /// the type of the receiver, the method expected to receive the message, /// and the form of the message send. - QualType getMessageSendResultType(QualType ReceiverType, - ObjCMethodDecl *Method, - bool isClassMessage, bool isSuperMessage); + QualType getMessageSendResultType(const Expr *Receiver, QualType ReceiverType, + ObjCMethodDecl *Method, bool isClassMessage, + bool isSuperMessage); /// If the given expression involves a message send to a method /// with a related result type, emit a note describing what happened. diff --git a/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h b/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h new file mode 100644 index 0000000000..192ac1261c --- /dev/null +++ b/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h @@ -0,0 +1,37 @@ +//===--- ClangSACheckers.h - Registration functions for Checkers *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declares the registation functions for the checkers defined in +// libclangStaticAnalyzerCheckers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_CLANGSACHECKERS_H +#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_CLANGSACHECKERS_H + +#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" + +namespace clang { + +namespace ento { +class CheckerManager; +class CheckerRegistry; + +#define GET_CHECKERS +#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \ + void register##CLASS(CheckerManager &mgr); +#include "clang/StaticAnalyzer/Checkers/Checkers.inc" +#undef CHECKER +#undef GET_CHECKERS + +} // end ento namespace + +} // end clang namespace + +#endif diff --git a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td index 15034fc689..453e189fcc 100644 --- a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td +++ b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td @@ -32,6 +32,18 @@ class ParentPackage<Package P> { Package ParentPackage = P; } /// a '-help'-like command line option. class HelpText<string text> { string HelpText = text; } +/// Describes what kind of documentation exists for the checker. +class DocumentationEnum<bits<2> val> { + bits<2> Documentation = val; +} +def NotDocumented : DocumentationEnum<0>; +def HasDocumentation : DocumentationEnum<1>; +def HasAlphaDocumentation : DocumentationEnum<2>; + +class Documentation<DocumentationEnum val> { + bits<2> Documentation = val.Documentation; +} + /// Describes a checker. Every builtin checker has to be registered with the use /// of this class (out-of-trunk checkers loaded from plugins obviously don't). /// Note that a checker has a name (e.g.: 'NullDereference'), and a fullname, @@ -40,5 +52,6 @@ class HelpText<string text> { string HelpText = text; } class Checker<string name = ""> { string CheckerName = name; string HelpText; + bits<2> Documentation; Package ParentPackage; } diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 9feb5a8766..1bb3da7a24 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -102,84 +102,106 @@ def CloneDetectionAlpha : Package<"clone">, ParentPackage<Alpha>; let ParentPackage = Core in { def DereferenceChecker : Checker<"NullDereference">, - HelpText<"Check for dereferences of null pointers">; + HelpText<"Check for dereferences of null pointers">, + Documentation<HasDocumentation>; def CallAndMessageChecker : Checker<"CallAndMessage">, HelpText<"Check for logical errors for function calls and Objective-C " "message expressions (e.g., uninitialized arguments, null function " - "pointers)">; + "pointers)">, + Documentation<HasDocumentation>; def NonNullParamChecker : Checker<"NonNullParamChecker">, HelpText<"Check for null pointers passed as arguments to a function whose " - "arguments are references or marked with the 'nonnull' attribute">; + "arguments are references or marked with the 'nonnull' attribute">, + Documentation<HasDocumentation>; def VLASizeChecker : Checker<"VLASize">, - HelpText<"Check for declarations of VLA of undefined or zero size">; + HelpText<"Check for declarations of VLA of undefined or zero size">, + Documentation<HasDocumentation>; def DivZeroChecker : Checker<"DivideZero">, - HelpText<"Check for division by zero">; + HelpText<"Check for division by zero">, + Documentation<HasDocumentation>; def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">, - HelpText<"Check for undefined results of binary operators">; + HelpText<"Check for undefined results of binary operators">, + Documentation<HasDocumentation>; def StackAddrEscapeChecker : Checker<"StackAddressEscape">, - HelpText<"Check that addresses to stack memory do not escape the function">; + HelpText<"Check that addresses to stack memory do not escape the function">, + Documentation<HasDocumentation>; def DynamicTypePropagation : Checker<"DynamicTypePropagation">, - HelpText<"Generate dynamic type information">; + HelpText<"Generate dynamic type information">, + Documentation<NotDocumented>; def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">, - HelpText<"Assume that const string-like globals are non-null">; + HelpText<"Assume that const string-like globals are non-null">, + Documentation<NotDocumented>; } // end "core" let ParentPackage = CoreAlpha in { def BoolAssignmentChecker : Checker<"BoolAssignment">, - HelpText<"Warn about assigning non-{0,1} values to Boolean variables">; + HelpText<"Warn about assigning non-{0,1} values to Boolean variables">, + Documentation<HasAlphaDocumentation>; def CastSizeChecker : Checker<"CastSize">, HelpText<"Check when casting a malloc'ed type T, whether the size is a " - "multiple of the size of T">; + "multiple of the size of T">, + Documentation<HasAlphaDocumentation>; def CastToStructChecker : Checker<"CastToStruct">, - HelpText<"Check for cast from non-struct pointer to struct pointer">; + HelpText<"Check for cast from non-struct pointer to struct pointer">, + Documentation<HasAlphaDocumentation>; def ConversionChecker : Checker<"Conversion">, - HelpText<"Loss of sign/precision in implicit conversions">; + HelpText<"Loss of sign/precision in implicit conversions">, + Documentation<HasAlphaDocumentation>; def IdenticalExprChecker : Checker<"IdenticalExpr">, - HelpText<"Warn about unintended use of identical expressions in operators">; + HelpText<"Warn about unintended use of identical expressions in operators">, + Documentation<HasAlphaDocumentation>; def FixedAddressChecker : Checker<"FixedAddr">, - HelpText<"Check for assignment of a fixed address to a pointer">; + HelpText<"Check for assignment of a fixed address to a pointer">, + Documentation<HasAlphaDocumentation>; def PointerArithChecker : Checker<"PointerArithm">, HelpText<"Check for pointer arithmetic on locations other than array " - "elements">; + "elements">, + Documentation<HasAlphaDocumentation>; def PointerSubChecker : Checker<"PointerSub">, HelpText<"Check for pointer subtractions on two pointers pointing to " - "different memory chunks">; + "different memory chunks">, + Documentation<HasAlphaDocumentation>; def SizeofPointerChecker : Checker<"SizeofPtr">, - HelpText<"Warn about unintended use of sizeof() on pointer expressions">; + HelpText<"Warn about unintended use of sizeof() on pointer expressions">, + Documentation<HasAlphaDocumentation>; def CallAndMessageUnInitRefArg : Checker<"CallAndMessageUnInitRefArg">, HelpText<"Check for logical errors for function calls and Objective-C " "message expressions (e.g., uninitialized arguments, null function " - "pointers, and pointer to undefined variables)">; + "pointers, and pointer to undefined variables)">, + Documentation<HasAlphaDocumentation>; def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">, HelpText<"Check for division by variable that is later compared against 0. " - "Either the comparison is useless or there is division by zero.">; + "Either the comparison is useless or there is division by zero.">, + Documentation<HasAlphaDocumentation>; def DynamicTypeChecker : Checker<"DynamicTypeChecker">, HelpText<"Check for cases where the dynamic and the static type of an object " - "are unrelated.">; + "are unrelated.">, + Documentation<HasAlphaDocumentation>; def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">, - HelpText<"Check that addresses to stack memory do not escape the function">; + HelpText<"Check that addresses to stack memory do not escape the function">, + Documentation<HasAlphaDocumentation>; } // end "alpha.core" @@ -187,33 +209,40 @@ let ParentPackage = Nullability in { def NullPassedToNonnullChecker : Checker<"NullPassedToNonnull">, HelpText<"Warns when a null pointer is passed to a pointer which has a " - "_Nonnull type.">; + "_Nonnull type.">, + Documentation<HasDocumentation>; def NullReturnedFromNonnullChecker : Checker<"NullReturnedFromNonnull">, HelpText<"Warns when a null pointer is returned from a function that has " - "_Nonnull return type.">; + "_Nonnull return type.">, + Documentation<HasDocumentation>; def NullableDereferencedChecker : Checker<"NullableDereferenced">, - HelpText<"Warns when a nullable pointer is dereferenced.">; + HelpText<"Warns when a nullable pointer is dereferenced.">, + Documentation<HasDocumentation>; def NullablePassedToNonnullChecker : Checker<"NullablePassedToNonnull">, HelpText<"Warns when a nullable pointer is passed to a pointer which has a " - "_Nonnull type.">; + "_Nonnull type.">, + Documentation<HasDocumentation>; def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">, HelpText<"Warns when a nullable pointer is returned from a function that has " - "_Nonnull return type.">; + "_Nonnull return type.">, + Documentation<NotDocumented>; } // end "nullability" let ParentPackage = APIModeling in { def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">, - HelpText<"Improve modeling of the C standard library functions">; + HelpText<"Improve modeling of the C standard library functions">, + Documentation<NotDocumented>; def TrustNonnullChecker : Checker<"TrustNonnull">, HelpText<"Trust that returns from framework methods annotated with _Nonnull " - "are not null">; + "are not null">, + Documentation<NotDocumented>; } // end "apiModeling" @@ -225,10 +254,12 @@ let ParentPackage = CoreBuiltin in { def NoReturnFunctionChecker : Checker<"NoReturnFunctions">, HelpText<"Evaluate \"panic\" functions that are known to not return to the " - "caller">; + "caller">, + Documentation<NotDocumented>; def BuiltinFunctionChecker : Checker<"BuiltinFunctions">, - HelpText<"Evaluate compiler builtin functions (e.g., alloca())">; + HelpText<"Evaluate compiler builtin functions (e.g., alloca())">, + Documentation<NotDocumented>; } // end "core.builtin" @@ -239,19 +270,24 @@ def BuiltinFunctionChecker : Checker<"BuiltinFunctions">, let ParentPackage = CoreUninitialized in { def UndefinedArraySubscriptChecker : Checker<"ArraySubscript">, - HelpText<"Check for uninitialized values used as array subscripts">; + HelpText<"Check for uninitialized values used as array subscripts">, + Documentation<HasDocumentation>; def UndefinedAssignmentChecker : Checker<"Assign">, - HelpText<"Check for assigning uninitialized values">; + HelpText<"Check for assigning uninitialized values">, + Documentation<HasDocumentation>; def UndefBranchChecker : Checker<"Branch">, - HelpText<"Check for uninitialized values used as branch conditions">; + HelpText<"Check for uninitialized values used as branch conditions">, + Documentation<HasDocumentation>; def UndefCapturedBlockVarChecker : Checker<"CapturedBlockVariable">, - HelpText<"Check for blocks that capture uninitialized values">; + HelpText<"Check for blocks that capture uninitialized values">, + Documentation<NotDocumented>; def ReturnUndefChecker : Checker<"UndefReturn">, - HelpText<"Check for uninitialized values being returned to the caller">; + HelpText<"Check for uninitialized values being returned to the caller">, + Documentation<HasDocumentation>; } // end "core.uninitialized" @@ -263,24 +299,33 @@ let ParentPackage = Cplusplus in { def InnerPointerChecker : Checker<"InnerPointer">, HelpText<"Check for inner pointers of C++ containers used after " - "re/deallocation">; + "re/deallocation">, + Documentation<NotDocumented>; def NewDeleteChecker : Checker<"NewDelete">, HelpText<"Check for double-free and use-after-free problems. Traces memory " - "managed by new/delete.">; + "managed by new/delete.">, + Documentation<HasDocumentation>; def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">, - HelpText<"Check for memory leaks. Traces memory managed by new/delete.">; + HelpText<"Check for memory leaks. Traces memory managed by new/delete.">, + Documentation<HasDocumentation>; def CXXSelfAssignmentChecker : Checker<"SelfAssignment">, - HelpText<"Checks C++ copy and move assignment operators for self assignment">; + HelpText<"Checks C++ copy and move assignment operators for self assignment">, + Documentation<NotDocumented>; + +def MoveChecker: Checker<"Move">, + HelpText<"Find use-after-move bugs in C++">, + Documentation<HasDocumentation>; } // end: "cplusplus" let ParentPackage = CplusplusOptIn in { def VirtualCallChecker : Checker<"VirtualCall">, - HelpText<"Check virtual function calls during construction or destruction">; + HelpText<"Check virtual function calls during construction or destruction">, + Documentation<HasDocumentation>; } // end: "optin.cplusplus" @@ -288,26 +333,29 @@ let ParentPackage = CplusplusAlpha in { def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, HelpText<"Reports destructions of polymorphic objects with a non-virtual " - "destructor in their base class">; + "destructor in their base class">, + Documentation<HasAlphaDocumentation>; def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">, - HelpText<"Check integer to enumeration casts for out of range values">; + HelpText<"Check integer to enumeration casts for out of range values">, + Documentation<HasAlphaDocumentation>; def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">, - HelpText<"Check for use of invalidated iterators">; + HelpText<"Check for use of invalidated iterators">, + Documentation<HasAlphaDocumentation>; def IteratorRangeChecker : Checker<"IteratorRange">, - HelpText<"Check for iterators used outside their valid ranges">; + HelpText<"Check for iterators used outside their valid ranges">, + Documentation<HasAlphaDocumentation>; def MismatchedIteratorChecker : Checker<"MismatchedIterator">, HelpText<"Check for use of iterators of different containers where iterators " - "of the same container are expected">; - -def MoveChecker: Checker<"Move">, - HelpText<"Find use-after-move bugs in C++">; + "of the same container are expected">, + Documentation<HasAlphaDocumentation>; def UninitializedObjectChecker: Checker<"UninitializedObject">, - HelpText<"Reports uninitialized fields after object construction">; + HelpText<"Reports uninitialized fields after object construction">, + Documentation<HasAlphaDocumentation>; } // end: "alpha.cplusplus" @@ -319,13 +367,16 @@ def UninitializedObjectChecker: Checker<"UninitializedObject">, let ParentPackage = Valist in { def UninitializedChecker : Checker<"Uninitialized">, - HelpText<"Check for usages of uninitialized (or already released) va_lists.">; + HelpText<"Check for usages of uninitialized (or already released) va_lists.">, + Documentation<NotDocumented>; def UnterminatedChecker : Checker<"Unterminated">, - HelpText<"Check for va_lists which are not released by a va_end call.">; + HelpText<"Check for va_lists which are not released by a va_end call.">, + Documentation<NotDocumented>; def CopyToSelfChecker : Checker<"CopyToSelf">, - HelpText<"Check for va_lists which are copied onto itself.">; + HelpText<"Check for va_lists which are copied onto itself.">, + Documentation<NotDocumented>; } // end : "valist" @@ -337,14 +388,16 @@ let ParentPackage = DeadCode in { def DeadStoresChecker : Checker<"DeadStores">, HelpText<"Check for values stored to variables that are never read " - "afterwards">; + "afterwards">, + Documentation<HasDocumentation>; } // end DeadCode let ParentPackage = DeadCodeAlpha in { def UnreachableCodeChecker : Checker<"UnreachableCode">, - HelpText<"Check unreachable code">; + HelpText<"Check unreachable code">, + Documentation<HasAlphaDocumentation>; } // end "alpha.deadcode" @@ -355,7 +408,8 @@ def UnreachableCodeChecker : Checker<"UnreachableCode">, let ParentPackage = Performance in { def PaddingChecker : Checker<"Padding">, - HelpText<"Check for excessively padded structs.">; + HelpText<"Check for excessively padded structs.">, + Documentation<NotDocumented>; } // end: "padding" @@ -366,29 +420,40 @@ def PaddingChecker : Checker<"Padding">, let ParentPackage = InsecureAPI in { def bcmp : Checker<"bcmp">, - HelpText<"Warn on uses of the 'bcmp' function">; + HelpText<"Warn on uses of the 'bcmp' function">, + Documentation<HasDocumentation>; def bcopy : Checker<"bcopy">, - HelpText<"Warn on uses of the 'bcopy' function">; + HelpText<"Warn on uses of the 'bcopy' function">, + Documentation<HasDocumentation>; def bzero : Checker<"bzero">, - HelpText<"Warn on uses of the 'bzero' function">; + HelpText<"Warn on uses of the 'bzero' function">, + Documentation<HasDocumentation>; def gets : Checker<"gets">, - HelpText<"Warn on uses of the 'gets' function">; + HelpText<"Warn on uses of the 'gets' function">, + Documentation<HasDocumentation>; def getpw : Checker<"getpw">, - HelpText<"Warn on uses of the 'getpw' function">; + HelpText<"Warn on uses of the 'getpw' function">, + Documentation<HasDocumentation>; def mktemp : Checker<"mktemp">, - HelpText<"Warn on uses of the 'mktemp' function">; + HelpText<"Warn on uses of the 'mktemp' function">, + Documentation<HasDocumentation>; def mkstemp : Checker<"mkstemp">, HelpText<"Warn when 'mkstemp' is passed fewer than 6 X's in the format " - "string">; + "string">, + Documentation<HasDocumentation>; def rand : Checker<"rand">, - HelpText<"Warn on uses of the 'rand', 'random', and related functions">; + HelpText<"Warn on uses of the 'rand', 'random', and related functions">, + Documentation<HasDocumentation>; def strcpy : Checker<"strcpy">, - HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">; + HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">, + Documentation<HasDocumentation>; def vfork : Checker<"vfork">, - HelpText<"Warn on uses of the 'vfork' function">; + HelpText<"Warn on uses of the 'vfork' function">, + Documentation<HasDocumentation>; def UncheckedReturn : Checker<"UncheckedReturn">, HelpText<"Warn on uses of functions whose return values must be always " - "checked">; + "checked">, + Documentation<HasDocumentation>; } // end "security.insecureAPI" @@ -396,29 +461,35 @@ let ParentPackage = Security in { def FloatLoopCounter : Checker<"FloatLoopCounter">, HelpText<"Warn on using a floating point value as a loop counter (CERT: " - "FLP30-C, FLP30-CPP)">; + "FLP30-C, FLP30-CPP)">, + Documentation<HasDocumentation>; } // end "security" let ParentPackage = SecurityAlpha in { def ArrayBoundChecker : Checker<"ArrayBound">, - HelpText<"Warn about buffer overflows (older checker)">; + HelpText<"Warn about buffer overflows (older checker)">, + Documentation<HasAlphaDocumentation>; def ArrayBoundCheckerV2 : Checker<"ArrayBoundV2">, - HelpText<"Warn about buffer overflows (newer checker)">; + HelpText<"Warn about buffer overflows (newer checker)">, + Documentation<HasAlphaDocumentation>; def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">, - HelpText<"Check for an out-of-bound pointer being returned to callers">; + HelpText<"Check for an out-of-bound pointer being returned to callers">, + Documentation<HasAlphaDocumentation>; def MallocOverflowSecurityChecker : Checker<"MallocOverflow">, - HelpText<"Check for overflows in the arguments to malloc()">; + HelpText<"Check for overflows in the arguments to malloc()">, + Documentation<HasAlphaDocumentation>; // Operating systems specific PROT_READ/PROT_WRITE values is not implemented, // the defaults are correct for several common operating systems though, // but may need to be overridden via the related analyzer-config flags. def MmapWriteExecChecker : Checker<"MmapWriteExec">, - HelpText<"Warn on mmap() calls that are both writable and executable">; + HelpText<"Warn on mmap() calls that are both writable and executable">, + Documentation<HasAlphaDocumentation>; } // end "alpha.security" @@ -429,7 +500,8 @@ def MmapWriteExecChecker : Checker<"MmapWriteExec">, let ParentPackage = Taint in { def GenericTaintChecker : Checker<"TaintPropagation">, - HelpText<"Generate taint information used by other checkers">; + HelpText<"Generate taint information used by other checkers">, + Documentation<HasAlphaDocumentation>; } // end "alpha.security.taint" @@ -440,39 +512,49 @@ def GenericTaintChecker : Checker<"TaintPropagation">, let ParentPackage = Unix in { def UnixAPIMisuseChecker : Checker<"API">, - HelpText<"Check calls to various UNIX/Posix functions">; + HelpText<"Check calls to various UNIX/Posix functions">, + Documentation<HasDocumentation>; def MallocChecker: Checker<"Malloc">, HelpText<"Check for memory leaks, double free, and use-after-free problems. " - "Traces memory managed by malloc()/free().">; + "Traces memory managed by malloc()/free().">, + Documentation<HasDocumentation>; def MallocSizeofChecker : Checker<"MallocSizeof">, - HelpText<"Check for dubious malloc arguments involving sizeof">; + HelpText<"Check for dubious malloc arguments involving sizeof">, + Documentation<HasDocumentation>; def MismatchedDeallocatorChecker : Checker<"MismatchedDeallocator">, - HelpText<"Check for mismatched deallocators.">; + HelpText<"Check for mismatched deallocators.">, + Documentation<HasDocumentation>; def VforkChecker : Checker<"Vfork">, - HelpText<"Check for proper usage of vfork">; + HelpText<"Check for proper usage of vfork">, + Documentation<HasDocumentation>; } // end "unix" let ParentPackage = UnixAlpha in { def ChrootChecker : Checker<"Chroot">, - HelpText<"Check improper use of chroot">; + HelpText<"Check improper use of chroot">, + Documentation<HasAlphaDocumentation>; def PthreadLockChecker : Checker<"PthreadLock">, - HelpText<"Simple lock -> unlock checker">; + HelpText<"Simple lock -> unlock checker">, + Documentation<HasAlphaDocumentation>; def StreamChecker : Checker<"Stream">, - HelpText<"Check stream handling functions">; + HelpText<"Check stream handling functions">, + Documentation<HasAlphaDocumentation>; def SimpleStreamChecker : Checker<"SimpleStream">, - HelpText<"Check for misuses of stream APIs">; + HelpText<"Check for misuses of stream APIs">, + Documentation<HasAlphaDocumentation>; def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">, - HelpText<"Check for calls to blocking functions inside a critical section">; + HelpText<"Check for calls to blocking functions inside a critical section">, + Documentation<HasAlphaDocumentation>; } // end "alpha.unix" @@ -480,24 +562,29 @@ let ParentPackage = CString in { def CStringNullArg : Checker<"NullArg">, HelpText<"Check for null pointers being passed as arguments to C string " - "functions">; + "functions">, + Documentation<HasDocumentation>; def CStringSyntaxChecker : Checker<"BadSizeArg">, HelpText<"Check the size argument passed into C string functions for common " - "erroneous patterns">; + "erroneous patterns">, + Documentation<HasDocumentation>; } // end "unix.cstring" let ParentPackage = CStringAlpha in { def CStringOutOfBounds : Checker<"OutOfBounds">, - HelpText<"Check for out-of-bounds access in string functions">; + HelpText<"Check for out-of-bounds access in string functions">, + Documentation<HasAlphaDocumentation>; def CStringBufferOverlap : Checker<"BufferOverlap">, - HelpText<"Checks for overlap in two buffer arguments">; + HelpText<"Checks for overlap in two buffer arguments">, + Documentation<HasAlphaDocumentation>; def CStringNotNullTerm : Checker<"NotNullTerminated">, - HelpText<"Check for arguments which are not null-terminating strings">; + HelpText<"Check for arguments which are not null-terminating strings">, + Documentation<HasAlphaDocumentation>; } // end "alpha.unix.cstring" @@ -509,19 +596,24 @@ let ParentPackage = OSX in { def NumberObjectConversionChecker : Checker<"NumberObjectConversion">, HelpText<"Check for erroneous conversions of objects representing numbers " - "into numbers">; + "into numbers">, + Documentation<NotDocumented>; def MacOSXAPIChecker : Checker<"API">, - HelpText<"Check for proper uses of various Apple APIs">; + HelpText<"Check for proper uses of various Apple APIs">, + Documentation<HasDocumentation>; def MacOSKeychainAPIChecker : Checker<"SecKeychainAPI">, - HelpText<"Check for proper uses of Secure Keychain APIs">; + HelpText<"Check for proper uses of Secure Keychain APIs">, + Documentation<HasDocumentation>; def ObjCPropertyChecker : Checker<"ObjCProperty">, - HelpText<"Check for proper uses of Objective-C properties">; + HelpText<"Check for proper uses of Objective-C properties">, + Documentation<NotDocumented>; def OSObjectRetainCountChecker : Checker<"OSObjectRetainCount">, - HelpText<"Check for leaks and improper reference count management for OSObject">; + HelpText<"Check for leaks and improper reference count management for OSObject">, + Documentation<NotDocumented>; } // end "osx" @@ -529,66 +621,84 @@ let ParentPackage = Cocoa in { def RunLoopAutoreleaseLeakChecker : Checker<"RunLoopAutoreleaseLeak">, HelpText<"Check for leaked memory in autorelease pools that will never be " - "drained">; + "drained">, + Documentation<NotDocumented>; def ObjCAtSyncChecker : Checker<"AtSync">, - HelpText<"Check for nil pointers used as mutexes for @synchronized">; + HelpText<"Check for nil pointers used as mutexes for @synchronized">, + Documentation<HasDocumentation>; def NilArgChecker : Checker<"NilArg">, - HelpText<"Check for prohibited nil arguments to ObjC method calls">; + HelpText<"Check for prohibited nil arguments to ObjC method calls">, + Documentation<HasDocumentation>; def ClassReleaseChecker : Checker<"ClassRelease">, HelpText<"Check for sending 'retain', 'release', or 'autorelease' directly " - "to a Class">; + "to a Class">, + Documentation<HasDocumentation>; def VariadicMethodTypeChecker : Checker<"VariadicMethodTypes">, HelpText<"Check for passing non-Objective-C types to variadic collection " - "initialization methods that expect only Objective-C types">; + "initialization methods that expect only Objective-C types">, + Documentation<HasDocumentation>; def NSAutoreleasePoolChecker : Checker<"NSAutoreleasePool">, HelpText<"Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC " - "mode">; + "mode">, + Documentation<HasDocumentation>; def ObjCMethSigsChecker : Checker<"IncompatibleMethodTypes">, HelpText<"Warn about Objective-C method signatures with type " - "incompatibilities">; + "incompatibilities">, + Documentation<HasDocumentation>; def ObjCUnusedIvarsChecker : Checker<"UnusedIvars">, - HelpText<"Warn about private ivars that are never used">; + HelpText<"Warn about private ivars that are never used">, + Documentation<HasDocumentation>; def ObjCSelfInitChecker : Checker<"SelfInit">, HelpText<"Check that 'self' is properly initialized inside an initializer " - "method">; + "method">, + Documentation<HasDocumentation>; def ObjCLoopChecker : Checker<"Loops">, - HelpText<"Improved modeling of loops using Cocoa collection types">; + HelpText<"Improved modeling of loops using Cocoa collection types">, + Documentation<NotDocumented>; def ObjCNonNilReturnValueChecker : Checker<"NonNilReturnValue">, - HelpText<"Model the APIs that are guaranteed to return a non-nil value">; + HelpText<"Model the APIs that are guaranteed to return a non-nil value">, + Documentation<NotDocumented>; def ObjCSuperCallChecker : Checker<"MissingSuperCall">, HelpText<"Warn about Objective-C methods that lack a necessary call to " - "super">; + "super">, + Documentation<NotDocumented>; def NSErrorChecker : Checker<"NSError">, - HelpText<"Check usage of NSError** parameters">; + HelpText<"Check usage of NSError** parameters">, + Documentation<HasDocumentation>; def RetainCountChecker : Checker<"RetainCount">, - HelpText<"Check for leaks and improper reference count management">; + HelpText<"Check for leaks and improper reference count management">, + Documentation<HasDocumentation>; def ObjCGenericsChecker : Checker<"ObjCGenerics">, - HelpText<"Check for type errors when using Objective-C generics">; + HelpText<"Check for type errors when using Objective-C generics">, + Documentation<HasDocumentation>; def ObjCDeallocChecker : Checker<"Dealloc">, HelpText<"Warn about Objective-C classes that lack a correct implementation " - "of -dealloc">; + "of -dealloc">, + Documentation<HasDocumentation>; def ObjCSuperDeallocChecker : Checker<"SuperDealloc">, - HelpText<"Warn about improper use of '[super dealloc]' in Objective-C">; + HelpText<"Warn about improper use of '[super dealloc]' in Objective-C">, + Documentation<HasDocumentation>; def AutoreleaseWriteChecker : Checker<"AutoreleaseWrite">, HelpText<"Warn about potentially crashing writes to autoreleasing objects " - "from different autoreleasing pools in Objective-C">; + "from different autoreleasing pools in Objective-C">, + Documentation<NotDocumented>; } // end "osx.cocoa" @@ -596,39 +706,47 @@ let ParentPackage = Performance in { def GCDAntipattern : Checker<"GCDAntipattern">, HelpText<"Check for performance anti-patterns when using Grand Central " - "Dispatch">; + "Dispatch">, + Documentation<NotDocumented>; } // end "optin.performance" let ParentPackage = CocoaAlpha in { def InstanceVariableInvalidation : Checker<"InstanceVariableInvalidation">, HelpText<"Check that the invalidatable instance variables are invalidated in " - "the methods annotated with objc_instance_variable_invalidator">; + "the methods annotated with objc_instance_variable_invalidator">, + Documentation<HasAlphaDocumentation>; def MissingInvalidationMethod : Checker<"MissingInvalidationMethod">, HelpText<"Check that the invalidation methods are present in classes that " - "contain invalidatable instance variables">; + "contain invalidatable instance variables">, + Documentation<HasAlphaDocumentation>; def DirectIvarAssignment : Checker<"DirectIvarAssignment">, - HelpText<"Check for direct assignments to instance variables">; + HelpText<"Check for direct assignments to instance variables">, + Documentation<HasAlphaDocumentation>; def DirectIvarAssignmentForAnnotatedFunctions : Checker<"DirectIvarAssignmentForAnnotatedFunctions">, HelpText<"Check for direct assignments to instance variables in the methods " - "annotated with objc_no_direct_instance_variable_assignment">; + "annotated with objc_no_direct_instance_variable_assignment">, + Documentation<HasAlphaDocumentation>; } // end "alpha.osx.cocoa" let ParentPackage = CoreFoundation in { def CFNumberChecker : Checker<"CFNumber">, - HelpText<"Check for proper uses of CFNumber APIs">; + HelpText<"Check for proper uses of CFNumber APIs">, + Documentation<HasDocumentation>; def CFRetainReleaseChecker : Checker<"CFRetainRelease">, - HelpText<"Check for null arguments to CFRetain/CFRelease/CFMakeCollectable">; + HelpText<"Check for null arguments to CFRetain/CFRelease/CFMakeCollectable">, + Documentation<HasDocumentation>; def CFErrorChecker : Checker<"CFError">, - HelpText<"Check usage of CFErrorRef* parameters">; + HelpText<"Check usage of CFErrorRef* parameters">, + Documentation<HasDocumentation>; } // end "osx.coreFoundation" @@ -636,10 +754,12 @@ let ParentPackage = Containers in { def ObjCContainersASTChecker : Checker<"PointerSizedValues">, HelpText<"Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with " - "non-pointer-size values">; + "non-pointer-size values">, + Documentation<HasDocumentation>; def ObjCContainersChecker : Checker<"OutOfBounds">, - HelpText<"Checks for index out-of-bounds when using 'CFArray' API">; + HelpText<"Checks for index out-of-bounds when using 'CFArray' API">, + Documentation<HasDocumentation>; } // end "osx.coreFoundation.containers" @@ -647,11 +767,13 @@ let ParentPackage = LocalizabilityOptIn in { def NonLocalizedStringChecker : Checker<"NonLocalizedStringChecker">, HelpText<"Warns about uses of non-localized NSStrings passed to UI methods " - "expecting localized NSStrings">; + "expecting localized NSStrings">, + Documentation<HasDocumentation>; def EmptyLocalizationContextChecker : Checker<"EmptyLocalizationContextChecker">, - HelpText<"Check that NSLocalizedString macros include a comment for context">; + HelpText<"Check that NSLocalizedString macros include a comment for context">, + Documentation<HasDocumentation>; } // end "optin.osx.cocoa.localizability" @@ -659,14 +781,16 @@ let ParentPackage = LocalizabilityAlpha in { def PluralMisuseChecker : Checker<"PluralMisuseChecker">, HelpText<"Warns against using one vs. many plural pattern in code when " - "generating localized strings.">; + "generating localized strings.">, + Documentation<HasAlphaDocumentation>; } // end "alpha.osx.cocoa.localizability" let ParentPackage = MPI in { def MPIChecker : Checker<"MPI-Checker">, - HelpText<"Checks MPI code">; + HelpText<"Checks MPI code">, + Documentation<HasDocumentation>; } // end "optin.mpi" @@ -677,7 +801,8 @@ def MPIChecker : Checker<"MPI-Checker">, let ParentPackage = LLVMAlpha in { def LLVMConventionsChecker : Checker<"Conventions">, - HelpText<"Check code for LLVM codebase conventions">; + HelpText<"Check code for LLVM codebase conventions">, + Documentation<HasAlphaDocumentation>; } // end "llvm" @@ -688,7 +813,8 @@ def LLVMConventionsChecker : Checker<"Conventions">, let ParentPackage = GoogleAPIModeling in { def GTestChecker : Checker<"GTest">, - HelpText<"Model gtest assertion APIs">; + HelpText<"Model gtest assertion APIs">, + Documentation<NotDocumented>; } // end "apiModeling.google" @@ -699,46 +825,64 @@ def GTestChecker : Checker<"GTest">, let ParentPackage = Debug in { def AnalysisOrderChecker : Checker<"AnalysisOrder">, - HelpText<"Print callbacks that are called during analysis in order">; + HelpText<"Print callbacks that are called during analysis in order">, + Documentation<NotDocumented>; def DominatorsTreeDumper : Checker<"DumpDominators">, - HelpText<"Print the dominance tree for a given CFG">; + HelpText<"Print the dominance tree for a given CFG">, + Documentation<NotDocumented>; def LiveVariablesDumper : Checker<"DumpLiveVars">, - HelpText<"Print results of live variable analysis">; + HelpText<"Print results of live variable analysis">, + Documentation<NotDocumented>; + +def LiveStatementsDumper : Checker<"DumpLiveStmts">, + HelpText<"Print results of live statement analysis">, + Documentation<NotDocumented>; def CFGViewer : Checker<"ViewCFG">, - HelpText<"View Control-Flow Graphs using GraphViz">; + HelpText<"View Control-Flow Graphs using GraphViz">, + Documentation<NotDocumented>; def CFGDumper : Checker<"DumpCFG">, - HelpText<"Display Control-Flow Graphs">; + HelpText<"Display Control-Flow Graphs">, + Documentation<NotDocumented>; def CallGraphViewer : Checker<"ViewCallGraph">, - HelpText<"View Call Graph using GraphViz">; + HelpText<"View Call Graph using GraphViz">, + Documentation<NotDocumented>; def CallGraphDumper : Checker<"DumpCallGraph">, - HelpText<"Display Call Graph">; + HelpText<"Display Call Graph">, + Documentation<NotDocumented>; def ConfigDumper : Checker<"ConfigDumper">, - HelpText<"Dump config table">; + HelpText<"Dump config table">, + Documentation<NotDocumented>; def TraversalDumper : Checker<"DumpTraversal">, - HelpText<"Print branch conditions as they are traversed by the engine">; + HelpText<"Print branch conditions as they are traversed by the engine">, + Documentation<NotDocumented>; def CallDumper : Checker<"DumpCalls">, - HelpText<"Print calls as they are traversed by the engine">; + HelpText<"Print calls as they are traversed by the engine">, + Documentation<NotDocumented>; def AnalyzerStatsChecker : Checker<"Stats">, - HelpText<"Emit warnings with analyzer statistics">; + HelpText<"Emit warnings with analyzer statistics">, + Documentation<NotDocumented>; def TaintTesterChecker : Checker<"TaintTest">, - HelpText<"Mark tainted symbols as such.">; + HelpText<"Mark tainted symbols as such.">, + Documentation<NotDocumented>; def ExprInspectionChecker : Checker<"ExprInspection">, - HelpText<"Check the analyzer's understanding of expressions">; + HelpText<"Check the analyzer's understanding of expressions">, + Documentation<NotDocumented>; def ExplodedGraphViewer : Checker<"ViewExplodedGraph">, - HelpText<"View Exploded Graphs using GraphViz">; + HelpText<"View Exploded Graphs using GraphViz">, + Documentation<NotDocumented>; } // end "debug" @@ -750,7 +894,8 @@ def ExplodedGraphViewer : Checker<"ViewExplodedGraph">, let ParentPackage = CloneDetectionAlpha in { def CloneChecker : Checker<"CloneChecker">, - HelpText<"Reports similar pieces of code.">; + HelpText<"Reports similar pieces of code.">, + Documentation<HasAlphaDocumentation>; } // end "clone" @@ -761,6 +906,7 @@ def CloneChecker : Checker<"CloneChecker">, let ParentPackage = PortabilityOptIn in { def UnixAPIPortabilityChecker : Checker<"UnixAPI">, - HelpText<"Finds implementation-defined behavior in UNIX/Posix functions">; + HelpText<"Finds implementation-defined behavior in UNIX/Posix functions">, + Documentation<NotDocumented>; } // end optin.portability diff --git a/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h b/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h deleted file mode 100644 index cf0a30a73d..0000000000 --- a/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h +++ /dev/null @@ -1,22 +0,0 @@ -//===--- ClangCheckers.h - Provides builtin checkers ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_CLANGCHECKERS_H -#define LLVM_CLANG_STATICANALYZER_CHECKERS_CLANGCHECKERS_H - -namespace clang { -namespace ento { -class CheckerRegistry; - -void registerBuiltinCheckers(CheckerRegistry ®istry); - -} // end namespace ento -} // end namespace clang - -#endif diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def index 8e5d8d3ad3..3cd54df7b1 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def @@ -275,7 +275,7 @@ ANALYZER_OPTION( ANALYZER_OPTION( bool, IsNaiveCTUEnabled, "experimental-enable-naive-ctu-analysis", "Whether naive cross translation unit analysis is enabled. This is an " - "experimental feature to inline functions from another translation units.", + "experimental feature to inline functions from other translation units.", false) ANALYZER_OPTION(bool, ShouldDisplayMacroExpansions, "expand-macros", @@ -344,8 +344,8 @@ ANALYZER_OPTION(StringRef, CTUDir, "ctu-dir", "The directory containing the CTU related files.", "") ANALYZER_OPTION(StringRef, CTUIndexName, "ctu-index-name", - "the name of the file containing the CTU index of functions.", - "externalFnMap.txt") + "the name of the file containing the CTU index of definitions.", + "externalDefMap.txt") ANALYZER_OPTION( StringRef, ModelPath, "model-path", diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h index 0e80e7bc19..d07525661a 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h @@ -16,7 +16,7 @@ namespace clang { namespace categories { extern const char * const CoreFoundationObjectiveC; extern const char * const LogicError; - extern const char * const MemoryCoreFoundationObjectiveC; + extern const char * const MemoryRefCount; extern const char * const MemoryError; extern const char * const UnixAPI; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index a53e8ee693..81dd83fc10 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -1138,9 +1138,16 @@ class CallEventManager { public: CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {} + /// Gets an outside caller given a callee context. CallEventRef<> getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State); + /// Gets a call event for a function call, Objective-C method call, + /// or a 'new' call. + CallEventRef<> + getCall(const Stmt *S, ProgramStateRef State, + const LocationContext *LC); + CallEventRef<> getSimpleCall(const CallExpr *E, ProgramStateRef State, const LocationContext *LCtx); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index bf01289a40..3d0ff4efa1 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -24,6 +24,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/Type.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index f544204497..c3a7028d87 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -555,15 +555,15 @@ public: MemRegionManager& getRegionManager() { return svalBuilder->getRegionManager(); } - const MemRegionManager& getRegionManager() const { + const MemRegionManager &getRegionManager() const { return svalBuilder->getRegionManager(); } CallEventManager &getCallEventManager() { return *CallEventMgr; } - StoreManager& getStoreManager() { return *StoreMgr; } - ConstraintManager& getConstraintManager() { return *ConstraintMgr; } - SubEngine* getOwningEngine() { return Eng; } + StoreManager &getStoreManager() { return *StoreMgr; } + ConstraintManager &getConstraintManager() { return *ConstraintMgr; } + SubEngine &getOwningEngine() { return *Eng; } ProgramStateRef removeDeadBindings(ProgramStateRef St, const StackFrameContext *LCtx, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 1b79bfc3f8..0efe96f67f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -530,9 +530,7 @@ public: return PTMDataType::getFromOpaqueValue(const_cast<void *>(Data)); } - bool isNullMemberPointer() const { - return getPTMData().isNull(); - } + bool isNullMemberPointer() const; const DeclaratorDecl *getDecl() const; diff --git a/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h b/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h index de16a1781a..4fcaa794c1 100644 --- a/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h +++ b/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h @@ -36,9 +36,26 @@ using namespace ento; namespace clang { namespace ento { -/// An ArgEffect summarizes the retain count behavior on an argument or receiver -/// to a function or method. -enum ArgEffect { +/// Determines the object kind of a tracked object. +enum class ObjKind { + /// Indicates that the tracked object is a CF object. + CF, + + /// Indicates that the tracked object is an Objective-C object. + ObjC, + + /// Indicates that the tracked object could be a CF or Objective-C object. + AnyObj, + + /// Indicates that the tracked object is a generalized object. + Generalized, + + /// Indicates that the tracking object is a descendant of a + /// referenced-counted OSObject, used in the Darwin kernel. + OS +}; + +enum ArgEffectKind { /// There is no effect. DoNothing, @@ -46,44 +63,35 @@ enum ArgEffect { /// the referenced object. Autorelease, - /// The argument is treated as if an -dealloc message had been sent to - /// the referenced object. + /// The argument is treated as if the referenced object was deallocated. Dealloc, - /// The argument has its reference count decreased by 1. This is as - /// if CFRelease has been called on the argument. + /// The argument has its reference count decreased by 1. DecRef, - /// The argument has its reference count decreased by 1. This is as - /// if a -release message has been sent to the argument. This differs - /// in behavior from DecRef when ARC is enabled. - DecRefMsg, - /// The argument has its reference count decreased by 1 to model /// a transferred bridge cast under ARC. DecRefBridgedTransferred, - /// The argument has its reference count increased by 1. This is as - /// if a -retain message has been sent to the argument. This differs - /// in behavior from IncRef when ARC is enabled. - IncRefMsg, - - /// The argument has its reference count increased by 1. This is as - /// if CFRetain has been called on the argument. + /// The argument has its reference count increased by 1. IncRef, - /// The argument acts as if has been passed to CFMakeCollectable, which - /// transfers the object to the Garbage Collector under GC. - MakeCollectable, - /// The argument is a pointer to a retain-counted object; on exit, the new - /// value of the pointer is a +0 value or NULL. + /// value of the pointer is a +0 value. UnretainedOutParameter, /// The argument is a pointer to a retain-counted object; on exit, the new - /// value of the pointer is a +1 value or NULL. + /// value of the pointer is a +1 value. RetainedOutParameter, + /// The argument is a pointer to a retain-counted object; on exit, the new + /// value of the pointer is a +1 value iff the return code is zero. + RetainedOutParameterOnZero, + + /// The argument is a pointer to a retain-counted object; on exit, the new + /// value of the pointer is a +1 value iff the return code is non-zero. + RetainedOutParameterOnNonZero, + /// The argument is treated as potentially escaping, meaning that /// even when its reference count hits 0 it should be treated as still /// possibly being alive as someone else *may* be holding onto the object. @@ -108,13 +116,27 @@ enum ArgEffect { /// count of the argument and all typestate tracking on that argument /// should cease. DecRefAndStopTrackingHard, +}; - /// Performs the combined functionality of DecRefMsg and StopTrackingHard. - /// - /// The models the effect that the called function decrements the reference - /// count of the argument and all typestate tracking on that argument - /// should cease. - DecRefMsgAndStopTrackingHard +/// An ArgEffect summarizes the retain count behavior on an argument or receiver +/// to a function or method. +class ArgEffect { + ArgEffectKind K; + ObjKind O; +public: + explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj) + : K(K), O(O) {} + + ArgEffectKind getKind() const { return K; } + ObjKind getObjKind() const { return O; } + + ArgEffect withKind(ArgEffectKind NewK) { + return ArgEffect(NewK, O); + } + + bool operator==(const ArgEffect &Other) const { + return K == Other.K && O == Other.O; + } }; /// RetEffect summarizes a call's retain/release behavior with respect @@ -125,18 +147,19 @@ public: /// Indicates that no retain count information is tracked for /// the return value. NoRet, + /// Indicates that the returned value is an owned (+1) symbol. OwnedSymbol, + /// Indicates that the returned value is an object with retain count /// semantics but that it is not owned (+0). This is the default /// for getters, etc. NotOwnedSymbol, - /// Indicates that the object is not owned and controlled by the - /// Garbage collector. - GCNotOwnedSymbol, + /// Indicates that the return value is an owned object when the /// receiver is also a tracked object. OwnedWhenTrackedReceiver, + // Treat this function as returning a non-tracked symbol even if // the function has been inlined. This is used where the call // site summary is more precise than the summary indirectly produced @@ -144,27 +167,11 @@ public: NoRetHard }; - /// Determines the object kind of a tracked object. - enum ObjKind { - /// Indicates that the tracked object is a CF object. This is - /// important between GC and non-GC code. - CF, - /// Indicates that the tracked object is an Objective-C object. - ObjC, - /// Indicates that the tracked object could be a CF or Objective-C object. - AnyObj, - /// Indicates that the tracked object is a generalized object. - Generalized, - - /// A descendant of OSObject. - OS - }; - private: Kind K; ObjKind O; - RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {} + RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {} public: Kind getKind() const { return K; } @@ -184,7 +191,7 @@ public: } static RetEffect MakeOwnedWhenTrackedReceiver() { - return RetEffect(OwnedWhenTrackedReceiver, ObjC); + return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC); } static RetEffect MakeOwned(ObjKind o) { @@ -193,9 +200,6 @@ public: static RetEffect MakeNotOwned(ObjKind o) { return RetEffect(NotOwnedSymbol, o); } - static RetEffect MakeGCNotOwned() { - return RetEffect(GCNotOwnedSymbol, ObjC); - } static RetEffect MakeNoRet() { return RetEffect(NoRet); } @@ -217,7 +221,9 @@ class CallEffects { RetEffect Ret; ArgEffect Receiver; - CallEffects(const RetEffect &R) : Ret(R) {} + CallEffects(const RetEffect &R, + ArgEffect Receiver = ArgEffect(DoNothing, ObjKind::AnyObj)) + : Ret(R), Receiver(Receiver) {} public: /// Returns the argument effects for a call. @@ -262,7 +268,8 @@ namespace llvm { template <> struct FoldingSetTrait<ArgEffect> { static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) { - ID.AddInteger((unsigned) X); + ID.AddInteger((unsigned) X.getKind()); + ID.AddInteger((unsigned) X.getObjKind()); } }; template <> struct FoldingSetTrait<RetEffect> { @@ -370,14 +377,15 @@ public: ArgEffect getReceiverEffect() const { return Receiver; } /// \return the effect on the "this" receiver of the method call. + /// This is only meaningful if the summary applies to CXXMethodDecl*. ArgEffect getThisEffect() const { return This; } /// Set the effect of the method on "this". void setThisEffect(ArgEffect e) { This = e; } bool isNoop() const { - return Ret == RetEffect::MakeNoRet() && Receiver == DoNothing - && DefaultArgEffect == MayEscape && This == DoNothing + return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing + && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing && Args.isEmpty(); } @@ -508,9 +516,6 @@ class RetainSummaryManager { /// AF - A factory for ArgEffects objects. ArgEffects::Factory AF; - /// ScratchArgs - A holding buffer for construct ArgEffects. - ArgEffects ScratchArgs; - /// ObjCAllocRetE - Default return effect for methods returning Objective-C /// objects. RetEffect ObjCAllocRetE; @@ -523,10 +528,6 @@ class RetainSummaryManager { /// effects. llvm::FoldingSet<CachedSummaryNode> SimpleSummaries; - /// getArgEffects - Returns a persistent ArgEffects object based on the - /// data in ScratchArgs. - ArgEffects getArgEffects(); - /// Create an OS object at +1. const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD); @@ -542,10 +543,8 @@ class RetainSummaryManager { /// Free the OS object. const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD); - enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable }; - const RetainSummary *getUnarySummary(const FunctionType* FT, - UnaryFuncKind func); + ArgEffectKind AE); const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD); const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD); @@ -553,27 +552,31 @@ class RetainSummaryManager { const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm); - const RetainSummary *getPersistentSummary(RetEffect RetEff, - ArgEffect ReceiverEff = DoNothing, - ArgEffect DefaultEff = MayEscape, - ArgEffect ThisEff = DoNothing) { - RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff, - ThisEff); + const RetainSummary * + getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs, + ArgEffect ReceiverEff = ArgEffect(DoNothing), + ArgEffect DefaultEff = ArgEffect(MayEscape), + ArgEffect ThisEff = ArgEffect(DoNothing)) { + RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff); return getPersistentSummary(Summ); } const RetainSummary *getDoNothingSummary() { - return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing); + return getPersistentSummary(RetEffect::MakeNoRet(), + ArgEffects(AF.getEmptyMap()), + ArgEffect(DoNothing), ArgEffect(DoNothing)); } const RetainSummary *getDefaultSummary() { return getPersistentSummary(RetEffect::MakeNoRet(), - DoNothing, MayEscape); + ArgEffects(AF.getEmptyMap()), + ArgEffect(DoNothing), ArgEffect(MayEscape)); } const RetainSummary *getPersistentStopSummary() { - return getPersistentSummary(RetEffect::MakeNoRet(), - StopTracking, StopTracking); + return getPersistentSummary( + RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()), + ArgEffect(StopTracking), ArgEffect(StopTracking)); } void InitializeClassMethodSummaries(); @@ -646,11 +649,9 @@ class RetainSummaryManager { /// Apply the annotation of {@code pd} in function {@code FD} /// to the resulting summary stored in out-parameter {@code Template}. /// \return whether an annotation was applied. - bool applyFunctionParamAnnotationEffect(const ParmVarDecl *pd, - unsigned parm_idx, - const FunctionDecl *FD, - ArgEffects::Factory &AF, - RetainSummaryTemplate &Template); + bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx, + const NamedDecl *FD, + RetainSummaryTemplate &Template); public: RetainSummaryManager(ASTContext &ctx, @@ -661,10 +662,10 @@ public: ARCEnabled(usesARC), TrackObjCAndCFObjects(trackObjCAndCFObjects), TrackOSObjects(trackOSObjects), - AF(BPAlloc), ScratchArgs(AF.getEmptyMap()), - ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC) - : RetEffect::MakeOwned(RetEffect::ObjC)), - ObjCInitRetE(usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC) + AF(BPAlloc), + ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(ObjKind::ObjC) + : RetEffect::MakeOwned(ObjKind::ObjC)), + ObjCInitRetE(usesARC ? RetEffect::MakeNotOwned(ObjKind::ObjC) : RetEffect::MakeOwnedWhenTrackedReceiver()) { InitializeClassMethodSummaries(); InitializeMethodSummaries(); @@ -745,16 +746,18 @@ public: RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; } - /// \return True if the declaration has an attribute {@code T}, - /// AND we are tracking that attribute. False otherwise. + /// Determine whether a declaration {@code D} of correspondent type (return + /// type for functions/methods) {@code QT} has any of the given attributes, + /// provided they pass necessary validation checks AND tracking the given + /// attribute is enabled. + /// Returns the object kind corresponding to the present attribute, or None, + /// if none of the specified attributes are present. + /// Crashes if passed an attribute which is not explicitly handled. template <class T> - bool hasEnabledAttr(const Decl *D) { - return isAttrEnabled<T>() && D->hasAttr<T>(); - } + Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT); - /// Check whether we are tracking properties specified by the attributes. - template <class T> - bool isAttrEnabled(); + template <class T1, class T2, class... Others> + Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT); friend class RetainSummaryTemplate; }; diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h index 740754090d..966234492f 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h +++ b/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h @@ -81,6 +81,8 @@ namespace ento { /// "core.builtin", or the full name "core.builtin.NoReturnFunctionChecker". class CheckerRegistry { public: + CheckerRegistry(ArrayRef<std::string> plugins, DiagnosticsEngine &diags); + /// Initialization functions perform any necessary setup for a checker. /// They should include a call to CheckerManager::registerChecker. using InitializationFunction = void (*)(CheckerManager &); @@ -89,12 +91,16 @@ public: InitializationFunction Initialize; StringRef FullName; StringRef Desc; + StringRef DocumentationUri; - CheckerInfo(InitializationFunction fn, StringRef name, StringRef desc) - : Initialize(fn), FullName(name), Desc(desc) {} + CheckerInfo(InitializationFunction Fn, StringRef Name, StringRef Desc, + StringRef DocsUri) + : Initialize(Fn), FullName(Name), Desc(Desc), + DocumentationUri(DocsUri) {} }; using CheckerInfoList = std::vector<CheckerInfo>; + using CheckerInfoSet = llvm::SetVector<const CheckerRegistry::CheckerInfo *>; private: template <typename T> @@ -105,28 +111,27 @@ private: public: /// Adds a checker to the registry. Use this non-templated overload when your /// checker requires custom initialization. - void addChecker(InitializationFunction fn, StringRef fullName, - StringRef desc); + void addChecker(InitializationFunction Fn, StringRef FullName, StringRef Desc, + StringRef DocsUri); /// Adds a checker to the registry. Use this templated overload when your /// checker does not require any custom initialization. template <class T> - void addChecker(StringRef fullName, StringRef desc) { + void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri) { // Avoid MSVC's Compiler Error C2276: // http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx - addChecker(&CheckerRegistry::initializeManager<T>, fullName, desc); + addChecker(&CheckerRegistry::initializeManager<T>, FullName, Desc, DocsUri); } /// Initializes a CheckerManager by calling the initialization functions for /// all checkers specified by the given CheckerOptInfo list. The order of this /// list is significant; later options can be used to reverse earlier ones. /// This can be used to exclude certain checkers in an included package. - void initializeManager(CheckerManager &mgr, const AnalyzerOptions &Opts, - DiagnosticsEngine &diags) const; + void initializeManager(CheckerManager &mgr, + const AnalyzerOptions &Opts) const; /// Check if every option corresponds to a specific checker or package. - void validateCheckerOptions(const AnalyzerOptions &opts, - DiagnosticsEngine &diags) const; + void validateCheckerOptions(const AnalyzerOptions &opts) const; /// Prints the name and description of all checkers in this registry. /// This output is not intended to be machine-parseable. @@ -134,8 +139,11 @@ public: void printList(raw_ostream &out, const AnalyzerOptions &opts) const; private: + CheckerInfoSet getEnabledCheckers(const AnalyzerOptions &Opts) const; + mutable CheckerInfoList Checkers; mutable llvm::StringMap<size_t> Packages; + DiagnosticsEngine &Diags; }; } // namespace ento diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index 8fd45bf102..2e9d0502e6 100644 --- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h @@ -52,9 +52,11 @@ private: llvm::StringMap<Stmt *> &Bodies; }; -void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins); +void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins, + DiagnosticsEngine &diags); void printEnabledCheckerList(raw_ostream &OS, ArrayRef<std::string> plugins, - const AnalyzerOptions &opts); + const AnalyzerOptions &opts, + DiagnosticsEngine &diags); void printAnalyzerConfigList(raw_ostream &OS); } // end GR namespace diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index 358acf3e2d..662a980547 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -205,7 +205,7 @@ bool runToolOnCodeWithArgs( /// /// \return The resulting AST or null if an error occurred. std::unique_ptr<ASTUnit> -buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc", +buildASTFromCode(StringRef Code, StringRef FileName = "input.cc", std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::make_shared<PCHContainerOperations>()); @@ -223,10 +223,10 @@ buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc", /// /// \return The resulting AST or null if an error occurred. std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs( - const Twine &Code, const std::vector<std::string> &Args, - const Twine &FileName = "input.cc", const Twine &ToolName = "clang-tool", + StringRef Code, const std::vector<std::string> &Args, + StringRef FileName = "input.cc", StringRef ToolName = "clang-tool", std::shared_ptr<PCHContainerOperations> PCHContainerOps = - std::make_shared<PCHContainerOperations>(), + std::make_shared<PCHContainerOperations>(), ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster()); /// Utility to run a FrontendAction in a single clang invocation. diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap index cbcb62e214..1f32ffe0c1 100644 --- a/include/clang/module.modulemap +++ b/include/clang/module.modulemap @@ -39,7 +39,6 @@ module Clang_Basic { textual header "Basic/BuiltinsLe64.def" textual header "Basic/BuiltinsMips.def" textual header "Basic/BuiltinsNEON.def" - textual header "Basic/BuiltinsNios2.def" textual header "Basic/BuiltinsNVPTX.def" textual header "Basic/BuiltinsPPC.def" textual header "Basic/BuiltinsSystemZ.def" @@ -50,6 +49,7 @@ module Clang_Basic { textual header "Basic/CodeGenOptions.def" textual header "Basic/DiagnosticOptions.def" textual header "Basic/Features.def" + textual header "Basic/MSP430Target.def" textual header "Basic/LangOptions.def" textual header "Basic/OpenCLExtensions.def" textual header "Basic/OpenCLImageTypes.def" |