Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp

master 2e10b7a39b9, the last commit before the llvmorg-12-init tag, from
which release/11.x was branched.

Note that for now, I rolled back all our local changes to make merging
easier, and I will reapply the still-relevant ones after updating to
11.0.0-rc1.
This commit is contained in:
Dimitry Andric 2020-07-31 21:22:58 +00:00
commit 5ffd83dbcc
6179 changed files with 461071 additions and 218666 deletions

View file

@ -1,13 +1,12 @@
# $FreeBSD$
.arcconfig
.arclint
.clang-format
.clang-tidy
.git-blame-ignore-revs
.github/
.gitignore
CONTRIBUTING.md
README.md
clang/.arcconfig
clang/.clang-format
clang/.clang-tidy
clang/.gitignore
@ -66,6 +65,7 @@ clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
clang/lib/StaticAnalyzer/Core/CMakeLists.txt
clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
clang/lib/StaticAnalyzer/README.txt
clang/lib/Testing/CMakeLists.txt
clang/lib/Tooling/ASTDiff/CMakeLists.txt
clang/lib/Tooling/CMakeLists.txt
clang/lib/Tooling/Core/CMakeLists.txt
@ -137,7 +137,6 @@ clang/utils/token-delta.py
clang/utils/valgrind/
clang/www/
clang-tools-extra/
compiler-rt/.arcconfig
compiler-rt/.gitignore
compiler-rt/CMakeLists.txt
compiler-rt/CODE_OWNERS.TXT
@ -189,7 +188,9 @@ compiler-rt/lib/sanitizer_common/tests/
compiler-rt/lib/scudo/CMakeLists.txt
compiler-rt/lib/scudo/standalone/CMakeLists.txt
compiler-rt/lib/scudo/standalone/benchmarks/
compiler-rt/lib/scudo/standalone/fuzz/CMakeLists.txt
compiler-rt/lib/scudo/standalone/tests/
compiler-rt/lib/scudo/standalone/tools/
compiler-rt/lib/stats/CMakeLists.txt
compiler-rt/lib/tsan/.clang-format
compiler-rt/lib/tsan/CMakeLists.txt
@ -210,9 +211,9 @@ compiler-rt/unittests/
compiler-rt/utils/
compiler-rt/www/
debuginfo-tests/
flang/
libc/
libclc/
libcxx/.arcconfig
libcxx/.clang-format
libcxx/.gitignore
libcxx/CMakeLists.txt
@ -235,7 +236,6 @@ libcxx/test/
libcxx/utils/
libcxx/www/
libcxxabi/
libunwind/.arcconfig
libunwind/.clang-format
libunwind/CMakeLists.txt
libunwind/cmake/
@ -246,6 +246,7 @@ lld/CMakeLists.txt
lld/COFF/CMakeLists.txt
lld/Common/CMakeLists.txt
lld/ELF/CMakeLists.txt
lld/MachO/CMakeLists.txt
lld/MinGW/
lld/cmake/
lld/docs/CMakeLists.txt
@ -260,8 +261,8 @@ lld/tools/lld/CMakeLists.txt
lld/unittests/
lld/utils/
lld/wasm/
lldb/.arcconfig
lldb/.clang-format
lldb/.clang-tidy
lldb/.gitignore
lldb/CMakeLists.txt
lldb/CODE_OWNERS.txt
@ -304,29 +305,22 @@ lldb/source/Host/macosx/
lldb/source/Host/windows/
lldb/source/Initialization/CMakeLists.txt
lldb/source/Interpreter/CMakeLists.txt
lldb/source/Plugins/ABI/AArch64/CMakeLists.txt
lldb/source/Plugins/ABI/ARC/CMakeLists.txt
lldb/source/Plugins/ABI/ARM/CMakeLists.txt
lldb/source/Plugins/ABI/CMakeLists.txt
lldb/source/Plugins/ABI/MacOSX-arm/CMakeLists.txt
lldb/source/Plugins/ABI/MacOSX-arm64/CMakeLists.txt
lldb/source/Plugins/ABI/MacOSX-i386/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-arc/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-arm/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-arm64/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-hexagon/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-i386/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-mips/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-mips64/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-ppc/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-s390x/CMakeLists.txt
lldb/source/Plugins/ABI/SysV-x86_64/CMakeLists.txt
lldb/source/Plugins/ABI/Windows-x86_64/CMakeLists.txt
lldb/source/Plugins/ABI/Hexagon/CMakeLists.txt
lldb/source/Plugins/ABI/Mips/CMakeLists.txt
lldb/source/Plugins/ABI/PowerPC/CMakeLists.txt
lldb/source/Plugins/ABI/SystemZ/CMakeLists.txt
lldb/source/Plugins/ABI/X86/CMakeLists.txt
lldb/source/Plugins/Architecture/Arm/CMakeLists.txt
lldb/source/Plugins/Architecture/CMakeLists.txt
lldb/source/Plugins/Architecture/Mips/CMakeLists.txt
lldb/source/Plugins/Architecture/PPC64/CMakeLists.txt
lldb/source/Plugins/CMakeLists.txt
lldb/source/Plugins/Disassembler/CMakeLists.txt
lldb/source/Plugins/Disassembler/llvm/CMakeLists.txt
lldb/source/Plugins/Disassembler/LLVMC/CMakeLists.txt
lldb/source/Plugins/DynamicLoader/CMakeLists.txt
lldb/source/Plugins/DynamicLoader/Darwin-Kernel/
lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/CMakeLists.txt
@ -334,6 +328,7 @@ lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/
lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt
lldb/source/Plugins/DynamicLoader/Static/CMakeLists.txt
lldb/source/Plugins/DynamicLoader/Windows-DYLD/CMakeLists.txt
lldb/source/Plugins/DynamicLoader/wasm-DYLD/CMakeLists.txt
lldb/source/Plugins/ExpressionParser/CMakeLists.txt
lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt
lldb/source/Plugins/Instruction/ARM/CMakeLists.txt
@ -357,7 +352,6 @@ lldb/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/Go/
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/ObjC/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/RenderScript/CMakeLists.txt
@ -373,6 +367,7 @@ lldb/source/Plugins/ObjectFile/ELF/CMakeLists.txt
lldb/source/Plugins/ObjectFile/JIT/CMakeLists.txt
lldb/source/Plugins/ObjectFile/Mach-O/
lldb/source/Plugins/ObjectFile/PECOFF/
lldb/source/Plugins/ObjectFile/wasm/CMakeLists.txt
lldb/source/Plugins/OperatingSystem/CMakeLists.txt
lldb/source/Plugins/OperatingSystem/Python/CMakeLists.txt
lldb/source/Plugins/Platform/Android/
@ -412,7 +407,10 @@ lldb/source/Plugins/SymbolFile/Symtab/CMakeLists.txt
lldb/source/Plugins/SymbolVendor/CMakeLists.txt
lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt
lldb/source/Plugins/SymbolVendor/MacOSX/
lldb/source/Plugins/SymbolVendor/wasm/CMakeLists.txt
lldb/source/Plugins/SystemRuntime/
lldb/source/Plugins/TypeSystem/CMakeLists.txt
lldb/source/Plugins/TypeSystem/Clang/CMakeLists.txt
lldb/source/Plugins/UnwindAssembly/CMakeLists.txt
lldb/source/Plugins/UnwindAssembly/InstEmulation/CMakeLists.txt
lldb/source/Plugins/UnwindAssembly/x86/CMakeLists.txt
@ -436,13 +434,13 @@ lldb/tools/lldb-test/
lldb/tools/lldb-vscode/
lldb/unittests/
lldb/use_lldb_suite_root.py
lldb/utils/CMakeLists.txt
lldb/utils/TableGen/CMakeLists.txt
lldb/utils/lit-cpuid/
lldb/utils/lldb-dotest/
lldb/utils/lldb-repro/
lldb/utils/lui/
lldb/utils/test/
llgo/
llvm/.arcconfig
llvm/.clang-format
llvm/.clang-tidy
llvm/.gitattributes
@ -461,6 +459,9 @@ llvm/docs/
llvm/examples/
llvm/include/llvm/CMakeLists.txt
llvm/include/llvm/Config/
llvm/include/llvm/Frontend/CMakeLists.txt
llvm/include/llvm/Frontend/OpenACC/CMakeLists.txt
llvm/include/llvm/Frontend/OpenMP/CMakeLists.txt
llvm/include/llvm/IR/CMakeLists.txt
llvm/include/llvm/Support/CMakeLists.txt
llvm/include/llvm/Support/LICENSE.TXT
@ -534,6 +535,7 @@ llvm/lib/ExecutionEngine/RuntimeDyld/LLVMBuild.txt
llvm/lib/Extensions/
llvm/lib/Frontend/CMakeLists.txt
llvm/lib/Frontend/LLVMBuild.txt
llvm/lib/Frontend/OpenACC/CMakeLists.txt
llvm/lib/Frontend/OpenMP/CMakeLists.txt
llvm/lib/Frontend/OpenMP/LLVMBuild.txt
llvm/lib/FuzzMutate/CMakeLists.txt
@ -738,9 +740,11 @@ llvm/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/SystemZ/MCTargetDesc/LLVMBuild.txt
llvm/lib/Target/SystemZ/TargetInfo/CMakeLists.txt
llvm/lib/Target/SystemZ/TargetInfo/LLVMBuild.txt
llvm/lib/Target/VE/AsmParser/CMakeLists.txt
llvm/lib/Target/VE/AsmParser/LLVMBuild.txt
llvm/lib/Target/VE/CMakeLists.txt
llvm/lib/Target/VE/InstPrinter/CMakeLists.txt
llvm/lib/Target/VE/InstPrinter/LLVMBuild.txt
llvm/lib/Target/VE/Disassembler/CMakeLists.txt
llvm/lib/Target/VE/Disassembler/LLVMBuild.txt
llvm/lib/Target/VE/LLVMBuild.txt
llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/VE/MCTargetDesc/LLVMBuild.txt
@ -770,8 +774,6 @@ llvm/lib/Target/X86/README-X86-64.txt
llvm/lib/Target/X86/README.txt
llvm/lib/Target/X86/TargetInfo/CMakeLists.txt
llvm/lib/Target/X86/TargetInfo/LLVMBuild.txt
llvm/lib/Target/X86/Utils/CMakeLists.txt
llvm/lib/Target/X86/Utils/LLVMBuild.txt
llvm/lib/Target/XCore/CMakeLists.txt
llvm/lib/Target/XCore/Disassembler/CMakeLists.txt
llvm/lib/Target/XCore/Disassembler/LLVMBuild.txt
@ -871,6 +873,7 @@ llvm/tools/llvm-exegesis/
llvm/tools/llvm-extract/CMakeLists.txt
llvm/tools/llvm-extract/LLVMBuild.txt
llvm/tools/llvm-go/
llvm/tools/llvm-gsymutil/
llvm/tools/llvm-ifs/
llvm/tools/llvm-isel-fuzzer/
llvm/tools/llvm-itanium-demangle-fuzzer/
@ -890,6 +893,7 @@ llvm/tools/llvm-mc-disassemble-fuzzer/
llvm/tools/llvm-mca/CMakeLists.txt
llvm/tools/llvm-mca/LLVMBuild.txt
llvm/tools/llvm-microsoft-demangle-fuzzer/
llvm/tools/llvm-ml/
llvm/tools/llvm-modextract/CMakeLists.txt
llvm/tools/llvm-modextract/LLVMBuild.txt
llvm/tools/llvm-mt/
@ -942,7 +946,6 @@ llvm/utils/DSAclean.py
llvm/utils/DSAextract.py
llvm/utils/FileCheck/
llvm/utils/GenLibDeps.pl
llvm/utils/GetRepositoryPath
llvm/utils/GetSourceVersion
llvm/utils/KillTheDoctor/
llvm/utils/LLVMBuild.txt
@ -965,6 +968,7 @@ llvm/utils/bisect-skip-count
llvm/utils/bugpoint/
llvm/utils/bugpoint_gisel_reducer.py
llvm/utils/check-each-file
llvm/utils/check_ninja_deps.py
llvm/utils/chunk-print-before-all.py
llvm/utils/clang-parse-diagnostics-file
llvm/utils/codegen-diff
@ -984,7 +988,7 @@ llvm/utils/findsym.pl
llvm/utils/fpcmp/
llvm/utils/gdb-scripts/
llvm/utils/getsrcs.sh
llvm/utils/git-svn/
llvm/utils/git/
llvm/utils/gn/
llvm/utils/indirect_calls.py
llvm/utils/jedit/
@ -1025,11 +1029,11 @@ llvm/utils/vscode/
llvm/utils/wciia.py
llvm/utils/yaml-bench/
mlir/
openmp/.arcconfig
openmp/.gitignore
openmp/CMakeLists.txt
openmp/README.rst
openmp/cmake/
openmp/docs/
openmp/libomptarget/
openmp/runtime/.clang-format
openmp/runtime/CMakeLists.txt
@ -1044,3 +1048,4 @@ openmp/www/
parallel-libs/
polly/
pstl/
utils/

View file

@ -117,7 +117,7 @@ clang_ModuleMapDescriptor_setFrameworkModuleName(CXModuleMapDescriptor,
const char *name);
/**
* Sets the umbrealla header name that the module.map describes.
* Sets the umbrella header name that the module.map describes.
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode

File diff suppressed because it is too large Load diff

View file

@ -18,14 +18,23 @@
LLVM_CLANG_C_EXTERN_C_BEGIN
/* MSVC DLL import/export. */
#ifdef _MSC_VER
#ifdef _CINDEX_LIB_
#define CINDEX_LINKAGE __declspec(dllexport)
#else
#define CINDEX_LINKAGE __declspec(dllimport)
/* Windows DLL import/export. */
#ifndef CINDEX_NO_EXPORTS
#define CINDEX_EXPORTS
#endif
#ifdef _WIN32
#ifdef CINDEX_EXPORTS
#ifdef _CINDEX_LIB_
#define CINDEX_LINKAGE __declspec(dllexport)
#else
#define CINDEX_LINKAGE __declspec(dllimport)
#endif
#endif
#else
#elif defined(CINDEX_EXPORTS) && defined(__GNUC__)
#define CINDEX_LINKAGE __attribute__((visibility("default")))
#endif
#ifndef CINDEX_LINKAGE
#define CINDEX_LINKAGE
#endif

View file

@ -372,7 +372,7 @@ public:
bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
void dump() const;
void dump(raw_ostream &OS) const;
void dump(raw_ostream &OS, const ASTContext &Context) const;
void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
std::string getAsString(const ASTContext &Ctx, QualType Ty) const;

View file

@ -193,4 +193,4 @@ public:
} // clang
#endif // LLVM_CLANG_AST_ASTCONCEPT_H
#endif // LLVM_CLANG_AST_ASTCONCEPT_H

View file

@ -15,7 +15,7 @@
#define LLVM_CLANG_AST_ASTCONTEXT_H
#include "clang/AST/ASTContextAllocate.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/ASTFwd.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/ComparisonCategories.h"
@ -26,7 +26,6 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RawCommentList.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
@ -40,7 +39,6 @@
#include "clang/Basic/SanitizerBlacklist.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/XRayLists.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
@ -75,6 +73,7 @@
namespace llvm {
struct fltSemantics;
template <typename T, unsigned N> class SmallPtrSet;
} // namespace llvm
@ -94,6 +93,9 @@ class CXXConstructorDecl;
class CXXMethodDecl;
class CXXRecordDecl;
class DiagnosticsEngine;
class ParentMapContext;
class DynTypedNode;
class DynTypedNodeList;
class Expr;
class FixedPointSemantics;
class GlobalDecl;
@ -102,6 +104,7 @@ class MangleNumberingContext;
class MaterializeTemporaryExpr;
class MemberSpecializationInfo;
class Module;
struct MSGuidDeclParts;
class ObjCCategoryDecl;
class ObjCCategoryImplDecl;
class ObjCContainerDecl;
@ -114,11 +117,13 @@ class ObjCPropertyDecl;
class ObjCPropertyImplDecl;
class ObjCProtocolDecl;
class ObjCTypeParamDecl;
class OMPTraitInfo;
struct ParsedTargetAttr;
class Preprocessor;
class Stmt;
class StoredDeclsMap;
class TargetAttr;
class TargetInfo;
class TemplateDecl;
class TemplateParameterList;
class TemplateTemplateParmDecl;
@ -136,6 +141,7 @@ class Context;
} // namespace Builtin
enum BuiltinTemplateKind : int;
enum OpenCLTypeKind : uint8_t;
namespace comments {
@ -188,6 +194,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
DependentAddressSpaceTypes;
mutable llvm::FoldingSet<VectorType> VectorTypes;
mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes;
mutable llvm::FoldingSet<ConstantMatrixType> MatrixTypes;
mutable llvm::FoldingSet<DependentSizedMatrixType> DependentSizedMatrixTypes;
mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&>
FunctionProtoTypes;
@ -218,6 +226,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
llvm::FoldingSet<AttributedType> AttributedTypes;
mutable llvm::FoldingSet<PipeType> PipeTypes;
mutable llvm::FoldingSet<ExtIntType> ExtIntTypes;
mutable llvm::FoldingSet<DependentExtIntType> DependentExtIntTypes;
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@ -264,6 +274,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Mapping from __block VarDecls to BlockVarCopyInit.
llvm::DenseMap<const VarDecl *, BlockVarCopyInit> BlockVarCopyInits;
/// Mapping from GUIDs to the corresponding MSGuidDecl.
mutable llvm::FoldingSet<MSGuidDecl> MSGuidDecls;
/// Used to cleanups APValues stored in the AST.
mutable llvm::SmallVector<APValue *, 0> APValueCleanups;
@ -565,18 +578,9 @@ private:
const TargetInfo *AuxTarget = nullptr;
clang::PrintingPolicy PrintingPolicy;
std::unique_ptr<interp::Context> InterpContext;
ast_type_traits::TraversalKind Traversal = ast_type_traits::TK_AsIs;
std::unique_ptr<ParentMapContext> ParentMapCtx;
public:
ast_type_traits::TraversalKind getTraversalKind() const { return Traversal; }
void setTraversalKind(ast_type_traits::TraversalKind TK) { Traversal = TK; }
const Expr *traverseIgnored(const Expr *E) const;
Expr *traverseIgnored(Expr *E) const;
ast_type_traits::DynTypedNode
traverseIgnored(const ast_type_traits::DynTypedNode &N) const;
IdentifierTable &Idents;
SelectorTable &Selectors;
Builtin::Context &BuiltinInfo;
@ -587,46 +591,8 @@ public:
/// Returns the clang bytecode interpreter context.
interp::Context &getInterpContext();
/// Container for either a single DynTypedNode or for an ArrayRef to
/// DynTypedNode. For use with ParentMap.
class DynTypedNodeList {
using DynTypedNode = ast_type_traits::DynTypedNode;
llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode,
ArrayRef<DynTypedNode>> Storage;
bool IsSingleNode;
public:
DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
new (Storage.buffer) DynTypedNode(N);
}
DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
new (Storage.buffer) ArrayRef<DynTypedNode>(A);
}
const ast_type_traits::DynTypedNode *begin() const {
if (!IsSingleNode)
return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
->begin();
return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
}
const ast_type_traits::DynTypedNode *end() const {
if (!IsSingleNode)
return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
->end();
return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1;
}
size_t size() const { return end() - begin(); }
bool empty() const { return begin() == end(); }
const DynTypedNode &operator[](size_t N) const {
assert(N < size() && "Out of bounds!");
return *(begin() + N);
}
};
/// Returns the dynamic AST node parent map context.
ParentMapContext &getParentMapContext();
// A traversal scope limits the parts of the AST visible to certain analyses.
// RecursiveASTVisitor::TraverseAST will only visit reachable nodes, and
@ -638,35 +604,9 @@ public:
std::vector<Decl *> getTraversalScope() const { return TraversalScope; }
void setTraversalScope(const std::vector<Decl *> &);
/// Returns the parents of the given node (within the traversal scope).
///
/// Note that this will lazily compute the parents of all nodes
/// and store them for later retrieval. Thus, the first call is O(n)
/// in the number of AST nodes.
///
/// Caveats and FIXMEs:
/// Calculating the parent map over all AST nodes will need to load the
/// full AST. This can be undesirable in the case where the full AST is
/// expensive to create (for example, when using precompiled header
/// preambles). Thus, there are good opportunities for optimization here.
/// One idea is to walk the given node downwards, looking for references
/// to declaration contexts - once a declaration context is found, compute
/// the parent map for the declaration context; if that can satisfy the
/// request, loading the whole AST can be avoided. Note that this is made
/// more complex by statements in templates having multiple parents - those
/// problems can be solved by building closure over the templated parts of
/// the AST, which also avoids touching large parts of the AST.
/// Additionally, we will want to add an interface to already give a hint
/// where to search for the parents, for example when looking at a statement
/// inside a certain function.
///
/// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
/// NestedNameSpecifier or NestedNameSpecifierLoc.
template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node) {
return getParents(ast_type_traits::DynTypedNode::create(Node));
}
DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node);
/// Forwards to get node parents from the ParentMapContext. New callers should
/// use ParentMapContext::getParents() directly.
template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node);
const clang::PrintingPolicy &getPrintingPolicy() const {
return PrintingPolicy;
@ -717,7 +657,7 @@ public:
/// getRealTypeForBitwidth -
/// sets floating point QualTy according to specified bitwidth.
/// Returns empty type if there is no appropriate target types.
QualType getRealTypeForBitwidth(unsigned DestWidth) const;
QualType getRealTypeForBitwidth(unsigned DestWidth, bool ExplicitIEEE) const;
bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const;
@ -791,15 +731,7 @@ public:
RawComment *getRawCommentForDeclNoCache(const Decl *D) const;
public:
RawCommentList &getRawCommentList() {
return Comments;
}
void addComment(const RawComment &RC) {
assert(LangOpts.RetainCommentsFromSystemHeaders ||
!SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin()));
Comments.addComment(RC, LangOpts.CommentOpts, BumpAlloc);
}
void addComment(const RawComment &RC);
/// Return the documentation comment attached to a given declaration.
/// Returns nullptr if no comment is attached.
@ -959,7 +891,7 @@ public:
void addedLocalImportDecl(ImportDecl *Import);
static ImportDecl *getNextLocalImport(ImportDecl *Import) {
return Import->NextLocalImport;
return Import->getNextLocalImport();
}
using import_range = llvm::iterator_range<import_iterator>;
@ -987,13 +919,7 @@ public:
/// Get the additional modules in which the definition \p Def has
/// been merged.
ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def) {
auto MergedIt =
MergedDefModules.find(cast<NamedDecl>(Def->getCanonicalDecl()));
if (MergedIt == MergedDefModules.end())
return None;
return MergedIt->second;
}
ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def);
/// Add a declaration to the list of declarations that are initialized
/// for a module. This will typically be a global variable (with internal
@ -1038,6 +964,7 @@ public:
CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy,
SatUnsignedLongFractTy;
CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON
CanQualType BFloat16Ty;
CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3
CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
CanQualType Float128ComplexTy;
@ -1052,7 +979,8 @@ public:
#include "clang/Basic/OpenCLImageTypes.def"
CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
CanQualType OCLQueueTy, OCLReserveIDTy;
CanQualType OMPArraySectionTy;
CanQualType IncompleteMatrixIdxTy;
CanQualType OMPArraySectionTy, OMPArrayShapingTy, OMPIteratorTy;
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
CanQualType Id##Ty;
#include "clang/Basic/OpenCLExtensionTypes.def"
@ -1066,7 +994,10 @@ public:
// Decl used to help define __builtin_va_list for some targets.
// The decl is built when constructing 'BuiltinVaListDecl'.
mutable Decl *VaListTagDecl;
mutable Decl *VaListTagDecl = nullptr;
// Implicitly-declared type 'struct _GUID'.
mutable TagDecl *MSGuidTagDecl = nullptr;
ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
SelectorTable &sels, Builtin::Context &builtins);
@ -1278,12 +1209,20 @@ public:
/// Return a write_only pipe type for the specified type.
QualType getWritePipeType(QualType T) const;
/// Return an extended integer type with the specified signedness and bit
/// count.
QualType getExtIntType(bool Unsigned, unsigned NumBits) const;
/// Return a dependent extended integer type with the specified signedness and
/// bit count.
QualType getDependentExtIntType(bool Unsigned, Expr *BitsExpr) const;
/// Gets the struct used to keep track of the extended descriptor for
/// pointer to blocks.
QualType getBlockDescriptorExtendedType() const;
/// Map an AST Type to an OpenCLTypeKind enum value.
TargetInfo::OpenCLTypeKind getOpenCLTypeKind(const Type *T) const;
OpenCLTypeKind getOpenCLTypeKind(const Type *T) const;
/// Get address space for OpenCL type.
LangAS getOpenCLTypeAddrSpace(const Type *T) const;
@ -1358,6 +1297,12 @@ public:
/// Returns a vla type where known sizes are replaced with [*].
QualType getVariableArrayDecayedType(QualType Ty) const;
/// Return the unique reference to a scalable vector type of the specified
/// element type and scalable number of elements.
///
/// \pre \p EltTy must be a built-in type.
QualType getScalableVectorType(QualType EltTy, unsigned NumElts) const;
/// Return the unique reference to a vector type of the specified
/// element type and size.
///
@ -1385,6 +1330,20 @@ public:
Expr *SizeExpr,
SourceLocation AttrLoc) const;
/// Return the unique reference to the matrix type of the specified element
/// type and size
///
/// \pre \p ElementType must be a valid matrix element type (see
/// MatrixType::isValidElementType).
QualType getConstantMatrixType(QualType ElementType, unsigned NumRows,
unsigned NumColumns) const;
/// Return the unique reference to the matrix type of the specified element
/// type and size
QualType getDependentSizedMatrixType(QualType ElementType, Expr *RowExpr,
Expr *ColumnExpr,
SourceLocation AttrLoc) const;
QualType getDependentAddressSpaceType(QualType PointeeType,
Expr *AddrSpaceExpr,
SourceLocation AttrLoc) const;
@ -1518,6 +1477,8 @@ public:
QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
ArrayRef<ObjCProtocolDecl *> protocols) const;
void adjustObjCTypeParamBoundType(const ObjCTypeParamDecl *Orig,
ObjCTypeParamDecl *New) const;
bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
@ -1713,23 +1674,9 @@ public:
return NSCopyingName;
}
CanQualType getNSUIntegerType() const {
assert(Target && "Expected target to be initialized");
const llvm::Triple &T = Target->getTriple();
// Windows is LLP64 rather than LP64
if (T.isOSWindows() && T.isArch64Bit())
return UnsignedLongLongTy;
return UnsignedLongTy;
}
CanQualType getNSUIntegerType() const;
CanQualType getNSIntegerType() const {
assert(Target && "Expected target to be initialized");
const llvm::Triple &T = Target->getTriple();
// Windows is LLP64 rather than LP64
if (T.isOSWindows() && T.isArch64Bit())
return LongLongTy;
return LongTy;
}
CanQualType getNSIntegerType() const;
/// Retrieve the identifier 'bool'.
IdentifierInfo *getBoolName() const {
@ -1944,6 +1891,15 @@ public:
return getTypeDeclType(getBuiltinMSVaListDecl());
}
/// Retrieve the implicitly-predeclared 'struct _GUID' declaration.
TagDecl *getMSGuidTagDecl() const { return MSGuidTagDecl; }
/// Retrieve the implicitly-predeclared 'struct _GUID' type.
QualType getMSGuidType() const {
assert(MSGuidTagDecl && "asked for GUID type but MS extensions disabled");
return getTagDeclType(MSGuidTagDecl);
}
/// Return whether a declaration to a builtin is allowed to be
/// overloaded/redeclared.
bool canBuiltinBeRedeclared(const FunctionDecl *) const;
@ -2207,9 +2163,7 @@ public:
/// Return the alignment (in bytes) of the thrown exception object. This is
/// only meaningful for targets that allocate C++ exceptions in a system
/// runtime, such as those using the Itanium C++ ABI.
CharUnits getExnObjectAlignment() const {
return toCharUnitsFromBits(Target->getExnObjectAlignment());
}
CharUnits getExnObjectAlignment() const;
/// Get or compute information about the layout of the specified
/// record (struct/union/class) \p D, which indicates its size and field
@ -2627,7 +2581,7 @@ public:
QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
bool Unqualified = false, bool BlockReturnType = false);
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
bool Unqualified = false);
bool Unqualified = false, bool AllowCXX = false);
QualType mergeFunctionParameterTypes(QualType, QualType,
bool OfBlockPointer = false,
bool Unqualified = false);
@ -2848,6 +2802,10 @@ public:
/// PredefinedExpr to cache evaluated results.
StringLiteral *getPredefinedStringLiteralFromCache(StringRef Key) const;
/// Return a declaration for the global GUID object representing the given
/// GUID value.
MSGuidDecl *getMSGuidDecl(MSGuidDeclParts Parts) const;
/// Parses the target attributes passed in, and returns only the ones that are
/// valid feature names.
ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const;
@ -3026,8 +2984,6 @@ private:
llvm::PointerIntPair<StoredDeclsMap *, 1> LastSDM;
std::vector<Decl *> TraversalScope;
class ParentMap;
std::map<ast_type_traits::TraversalKind, std::unique_ptr<ParentMap>> Parents;
std::unique_ptr<VTableContextBase> VTContext;
@ -3040,6 +2996,7 @@ public:
PSF_Write = 0x2,
PSF_Execute = 0x4,
PSF_Implicit = 0x8,
PSF_ZeroInit = 0x10,
PSF_Invalid = 0x80000000U,
};
@ -3057,8 +3014,20 @@ public:
};
llvm::StringMap<SectionInfo> SectionInfos;
/// Return a new OMPTraitInfo object owned by this context.
OMPTraitInfo &getNewOMPTraitInfo();
private:
/// All OMPTraitInfo objects live in this collection, one per
/// `pragma omp [begin] declare variant` directive.
SmallVector<std::unique_ptr<OMPTraitInfo>, 4> OMPTraitInfoVector;
};
/// Insertion operator for diagnostics.
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const ASTContext::SectionInfo &Section);
/// Utility function for constructing a nullary selector.
inline Selector GetNullarySelector(StringRef name, ASTContext &Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
@ -3071,22 +3040,6 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
return Ctx.Selectors.getSelector(1, &II);
}
class TraversalKindScope {
ASTContext &Ctx;
ast_type_traits::TraversalKind TK = ast_type_traits::TK_AsIs;
public:
TraversalKindScope(ASTContext &Ctx,
llvm::Optional<ast_type_traits::TraversalKind> ScopeTK)
: Ctx(Ctx) {
TK = Ctx.getTraversalKind();
if (ScopeTK)
Ctx.setTraversalKind(*ScopeTK);
}
~TraversalKindScope() { Ctx.setTraversalKind(TK); }
};
} // namespace clang
// operator new and delete aren't allowed inside namespaces.

View file

@ -11,6 +11,7 @@
#include "clang/AST/ASTNodeTraverser.h"
#include "clang/AST/TextNodeDumper.h"
#include "clang/Basic/SourceManager.h"
namespace clang {
@ -23,18 +24,11 @@ class ASTDumper : public ASTNodeTraverser<ASTDumper, TextNodeDumper> {
const bool ShowColors;
public:
ASTDumper(raw_ostream &OS, const comments::CommandTraits *Traits,
const SourceManager *SM)
: ASTDumper(OS, Traits, SM, SM && SM->getDiagnostics().getShowColors()) {}
ASTDumper(raw_ostream &OS, const ASTContext &Context, bool ShowColors)
: NodeDumper(OS, Context, ShowColors), OS(OS), ShowColors(ShowColors) {}
ASTDumper(raw_ostream &OS, const comments::CommandTraits *Traits,
const SourceManager *SM, bool ShowColors)
: ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {}
ASTDumper(raw_ostream &OS, const comments::CommandTraits *Traits,
const SourceManager *SM, bool ShowColors,
const PrintingPolicy &PrintPolicy)
: NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS),
ShowColors(ShowColors) {}
ASTDumper(raw_ostream &OS, bool ShowColors)
: NodeDumper(OS, ShowColors), OS(OS), ShowColors(ShowColors) {}
TextNodeDumper &doGetNodeDelegate() { return NodeDumper; }

View file

@ -62,6 +62,8 @@ static const TerminalColor LocationColor = {llvm::raw_ostream::YELLOW, false};
static const TerminalColor ValueKindColor = {llvm::raw_ostream::CYAN, false};
// bitfield/objcproperty/objcsubscript/vectorcomponent
static const TerminalColor ObjectKindColor = {llvm::raw_ostream::CYAN, false};
// contains-errors
static const TerminalColor ErrorsColor = {llvm::raw_ostream::RED, true};
// Null statements
static const TerminalColor NullColor = {llvm::raw_ostream::BLUE, false};

View file

@ -27,8 +27,8 @@ class Type;
#include "clang/AST/TypeNodes.inc"
class CXXCtorInitializer;
class OMPClause;
#define OPENMP_CLAUSE(KIND, CLASSNAME) class CLASSNAME;
#include "clang/Basic/OpenMPKinds.def"
#define OMP_CLAUSE_CLASS(Enum, Str, Class) class Class;
#include "llvm/Frontend/OpenMP/OMPKinds.def"
} // end namespace clang

View file

@ -16,6 +16,7 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@ -349,6 +350,10 @@ class TypeSourceInfo;
return ToOrErr.takeError();
}
/// Import cleanup objects owned by ExprWithCleanup.
llvm::Expected<ExprWithCleanups::CleanupObject>
Import(ExprWithCleanups::CleanupObject From);
/// Import the given type from the "from" context into the "to"
/// context. A null type is imported as a null type (no error).
///

View file

@ -15,16 +15,20 @@
#ifndef LLVM_CLANG_AST_ASTNODETRAVERSER_H
#define LLVM_CLANG_AST_ASTNODETRAVERSER_H
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/AttrVisitor.h"
#include "clang/AST/CommentVisitor.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/LocInfoType.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TemplateArgumentVisitor.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeVisitor.h"
namespace clang {
class APValue;
/**
ASTNodeTraverser traverses the Clang AST for dumping purposes.
@ -49,6 +53,7 @@ struct {
void Visit(const OMPClause *C);
void Visit(const BlockDecl::Capture &C);
void Visit(const GenericSelectionExpr::ConstAssociation &A);
void Visit(const APValue &Value, QualType Ty);
};
*/
template <typename Derived, typename NodeDelegateType>
@ -65,8 +70,7 @@ class ASTNodeTraverser
/// not already been loaded.
bool Deserialize = false;
ast_type_traits::TraversalKind Traversal =
ast_type_traits::TraversalKind::TK_AsIs;
TraversalKind Traversal = TraversalKind::TK_AsIs;
NodeDelegateType &getNodeDelegate() {
return getDerived().doGetNodeDelegate();
@ -77,7 +81,7 @@ public:
void setDeserialize(bool D) { Deserialize = D; }
bool getDeserialize() const { return Deserialize; }
void SetTraversalKind(ast_type_traits::TraversalKind TK) { Traversal = TK; }
void SetTraversalKind(TraversalKind TK) { Traversal = TK; }
void Visit(const Decl *D) {
getNodeDelegate().AddChild([=] {
@ -108,12 +112,12 @@ public:
if (auto *E = dyn_cast_or_null<Expr>(S)) {
switch (Traversal) {
case ast_type_traits::TK_AsIs:
case TK_AsIs:
break;
case ast_type_traits::TK_IgnoreImplicitCastsAndParentheses:
case TK_IgnoreImplicitCastsAndParentheses:
S = E->IgnoreParenImpCasts();
break;
case ast_type_traits::TK_IgnoreUnlessSpelledInSource:
case TK_IgnoreUnlessSpelledInSource:
S = E->IgnoreUnlessSpelledInSource();
break;
}
@ -131,8 +135,7 @@ public:
if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S))
return;
if (isa<LambdaExpr>(S) &&
Traversal == ast_type_traits::TK_IgnoreUnlessSpelledInSource)
if (isa<LambdaExpr>(S) && Traversal == TK_IgnoreUnlessSpelledInSource)
return;
for (const Stmt *SubStmt : S->children())
@ -212,6 +215,10 @@ public:
});
}
void Visit(const APValue &Value, QualType Ty) {
getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(Value, Ty); });
}
void Visit(const comments::Comment *C, const comments::FullComment *FC) {
getNodeDelegate().AddChild([=] {
getNodeDelegate().Visit(C, FC);
@ -228,7 +235,7 @@ public:
});
}
void Visit(const ast_type_traits::DynTypedNode &N) {
void Visit(const DynTypedNode &N) {
// FIXME: Improve this with a switch or a visitor pattern.
if (const auto *D = N.get<Decl>())
Visit(D);
@ -353,8 +360,6 @@ public:
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
for (const auto &Arg : *T)
Visit(Arg);
if (T->isTypeAlias())
Visit(T->getAliasedType());
}
void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
Visit(T->getPointeeType());
@ -658,7 +663,7 @@ public:
}
void VisitLambdaExpr(const LambdaExpr *Node) {
if (Traversal == ast_type_traits::TK_IgnoreUnlessSpelledInSource) {
if (Traversal == TK_IgnoreUnlessSpelledInSource) {
for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
const auto *C = Node->capture_begin() + I;
if (!C->isExplicit())
@ -683,6 +688,15 @@ public:
Visit(A);
}
void VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) {
Visit(E->getParameter());
}
void VisitSubstNonTypeTemplateParmPackExpr(
const SubstNonTypeTemplateParmPackExpr *E) {
Visit(E->getParameterPack());
Visit(E->getArgumentPack());
}
void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
if (const VarDecl *CatchParam = Node->getCatchParamDecl())
Visit(CatchParam);
@ -691,6 +705,11 @@ public:
void VisitExpressionTemplateArgument(const TemplateArgument &TA) {
Visit(TA.getAsExpr());
}
void VisitTypeTemplateArgument(const TemplateArgument &TA) {
Visit(TA.getAsType());
}
void VisitPackTemplateArgument(const TemplateArgument &TA) {
for (const auto &TArg : TA.pack_elements())
Visit(TArg);

View file

@ -16,6 +16,7 @@
#define LLVM_CLANG_AST_ASTTYPETRAITS_H
#include "clang/AST/ASTFwd.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TypeLoc.h"
@ -33,8 +34,6 @@ namespace clang {
struct PrintingPolicy;
namespace ast_type_traits {
/// Defines how we descend a level in the AST when we pass
/// through expressions.
enum TraversalKind {
@ -138,6 +137,7 @@ private:
NKI_QualType,
NKI_TypeLoc,
NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
NKI_CXXBaseSpecifier,
NKI_CXXCtorInitializer,
NKI_NestedNameSpecifier,
NKI_Decl,
@ -150,8 +150,8 @@ private:
#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
#include "clang/AST/TypeNodes.inc"
NKI_OMPClause,
#define OPENMP_CLAUSE(TextualSpelling, Class) NKI_##Class,
#include "clang/Basic/OpenMPKinds.def"
#define OMP_CLAUSE_CLASS(Enum, Str, Class) NKI_##Class,
#include "llvm/Frontend/OpenMP/OMPKinds.def"
NKI_NumberOfKinds
};
@ -200,14 +200,15 @@ KIND_TO_KIND_ID(Decl)
KIND_TO_KIND_ID(Stmt)
KIND_TO_KIND_ID(Type)
KIND_TO_KIND_ID(OMPClause)
KIND_TO_KIND_ID(CXXBaseSpecifier)
#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
#include "clang/AST/DeclNodes.inc"
#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
#include "clang/AST/StmtNodes.inc"
#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
#include "clang/AST/TypeNodes.inc"
#define OPENMP_CLAUSE(TextualSpelling, Class) KIND_TO_KIND_ID(Class)
#include "clang/Basic/OpenMPKinds.def"
#define OMP_CLAUSE_CLASS(Enum, Str, Class) KIND_TO_KIND_ID(Class)
#include "llvm/Frontend/OpenMP/OMPKinds.def"
#undef KIND_TO_KIND_ID
inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) {
@ -277,7 +278,7 @@ public:
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
/// Dumps the node to the given output stream.
void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
void dump(llvm::raw_ostream &OS, const ASTContext &Context) const;
/// For nodes which represent textual entities in the source code,
/// return their SourceRange. For all other nodes, return SourceRange().
@ -465,22 +466,22 @@ private:
template <typename T>
struct DynTypedNode::BaseConverter<
T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type>
T, std::enable_if_t<std::is_base_of<Decl, T>::value>>
: public DynCastPtrConverter<T, Decl> {};
template <typename T>
struct DynTypedNode::BaseConverter<
T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type>
T, std::enable_if_t<std::is_base_of<Stmt, T>::value>>
: public DynCastPtrConverter<T, Stmt> {};
template <typename T>
struct DynTypedNode::BaseConverter<
T, typename std::enable_if<std::is_base_of<Type, T>::value>::type>
T, std::enable_if_t<std::is_base_of<Type, T>::value>>
: public DynCastPtrConverter<T, Type> {};
template <typename T>
struct DynTypedNode::BaseConverter<
T, typename std::enable_if<std::is_base_of<OMPClause, T>::value>::type>
T, std::enable_if_t<std::is_base_of<OMPClause, T>::value>>
: public DynCastPtrConverter<T, OMPClause> {};
template <>
@ -512,6 +513,10 @@ template <>
struct DynTypedNode::BaseConverter<
TypeLoc, void> : public ValueConverter<TypeLoc> {};
template <>
struct DynTypedNode::BaseConverter<CXXBaseSpecifier, void>
: public PtrConverter<CXXBaseSpecifier> {};
// The only operation we allow on unsupported types is \c get.
// This allows to conveniently use \c DynTypedNode when having an arbitrary
// AST node that is not supported, but prevents misuse - a user cannot create
@ -522,18 +527,29 @@ template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
}
};
} // end namespace ast_type_traits
// Previously these types were defined in the clang::ast_type_traits namespace.
// Provide typedefs so that legacy code can be fixed asynchronously.
namespace ast_type_traits {
using DynTypedNode = ::clang::DynTypedNode;
using ASTNodeKind = ::clang::ASTNodeKind;
using TraversalKind = ::clang::TraversalKind;
constexpr TraversalKind TK_AsIs = ::clang::TK_AsIs;
constexpr TraversalKind TK_IgnoreImplicitCastsAndParentheses =
::clang::TK_IgnoreImplicitCastsAndParentheses;
constexpr TraversalKind TK_IgnoreUnlessSpelledInSource =
::clang::TK_IgnoreUnlessSpelledInSource;
} // namespace ast_type_traits
} // end namespace clang
namespace llvm {
template <>
struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind>
: clang::ast_type_traits::ASTNodeKind::DenseMapInfo {};
struct DenseMapInfo<clang::ASTNodeKind> : clang::ASTNodeKind::DenseMapInfo {};
template <>
struct DenseMapInfo<clang::ast_type_traits::DynTypedNode>
: clang::ast_type_traits::DynTypedNode::DenseMapInfo {};
struct DenseMapInfo<clang::DynTypedNode> : clang::DynTypedNode::DenseMapInfo {};
} // end namespace llvm

View file

@ -13,13 +13,13 @@
#ifndef LLVM_CLANG_AST_ATTR_H
#define LLVM_CLANG_AST_ATTR_H
#include "clang/AST/ASTContextAllocate.h" // For Attrs.inc
#include "clang/AST/ASTFwd.h"
#include "clang/AST/AttrIterator.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/Sanitizers.h"
@ -40,6 +40,7 @@ class Expr;
class QualType;
class FunctionDecl;
class TypeSourceInfo;
class OMPTraitInfo;
/// Attr - This represents one attribute.
class Attr : public AttributeCommonInfo {

View file

@ -212,6 +212,9 @@ FLOATING_TYPE(LongDouble, LongDoubleTy)
// '_Float16'
FLOATING_TYPE(Float16, HalfTy)
// '__bf16'
FLOATING_TYPE(BFloat16, BFloat16Ty)
// '__float128'
FLOATING_TYPE(Float128, Float128Ty)
@ -310,11 +313,20 @@ PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
// context.
PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
// A placeholder type for incomplete matrix index expressions.
PLACEHOLDER_TYPE(IncompleteMatrixIdx, IncompleteMatrixIdxTy)
// A placeholder type for OpenMP array sections.
PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)
// A placeholder type for OpenMP array shaping operation.
PLACEHOLDER_TYPE(OMPArrayShaping, OMPArrayShapingTy)
// A placeholder type for OpenMP iterators.
PLACEHOLDER_TYPE(OMPIterator, OMPIteratorTy)
#ifdef LAST_BUILTIN_TYPE
LAST_BUILTIN_TYPE(OMPArraySection)
LAST_BUILTIN_TYPE(OMPIterator)
#undef LAST_BUILTIN_TYPE
#endif

View file

@ -119,7 +119,7 @@ class CXXBasePaths {
friend class CXXRecordDecl;
/// The type from which this search originated.
CXXRecordDecl *Origin = nullptr;
const CXXRecordDecl *Origin = nullptr;
/// Paths - The actual set of paths that can be taken from the
/// derived class to the same base class.
@ -225,8 +225,8 @@ public:
/// Retrieve the type from which this base-paths search
/// began
CXXRecordDecl *getOrigin() const { return Origin; }
void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; }
const CXXRecordDecl *getOrigin() const { return Origin; }
void setOrigin(const CXXRecordDecl *Rec) { Origin = Rec; }
/// Clear the base-paths results.
void clear();

View file

@ -140,6 +140,7 @@ FIELD(HasInheritedAssignment, 1, NO_MERGE)
/// @{
FIELD(NeedOverloadResolutionForCopyConstructor, 1, NO_MERGE)
FIELD(NeedOverloadResolutionForMoveConstructor, 1, NO_MERGE)
FIELD(NeedOverloadResolutionForCopyAssignment, 1, NO_MERGE)
FIELD(NeedOverloadResolutionForMoveAssignment, 1, NO_MERGE)
FIELD(NeedOverloadResolutionForDestructor, 1, NO_MERGE)
/// @}
@ -149,6 +150,7 @@ FIELD(NeedOverloadResolutionForDestructor, 1, NO_MERGE)
/// @{
FIELD(DefaultedCopyConstructorIsDeleted, 1, NO_MERGE)
FIELD(DefaultedMoveConstructorIsDeleted, 1, NO_MERGE)
FIELD(DefaultedCopyAssignmentIsDeleted, 1, NO_MERGE)
FIELD(DefaultedMoveAssignmentIsDeleted, 1, NO_MERGE)
FIELD(DefaultedDestructorIsDeleted, 1, NO_MERGE)
/// @}

View file

@ -74,7 +74,7 @@ public:
/// canonical type pointers.
template <typename U>
CanQual(const CanQual<U> &Other,
typename std::enable_if<std::is_base_of<T, U>::value, int>::type = 0);
std::enable_if_t<std::is_base_of<T, U>::value, int> = 0);
/// Retrieve the underlying type pointer, which refers to a
/// canonical type.
@ -264,6 +264,8 @@ public:
// Type predicates
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessBuiltinType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
@ -384,7 +386,7 @@ struct PointerLikeTypeTraits<clang::CanQual<T>> {
}
// qualifier information is encoded in the low bits.
enum { NumLowBitsAvailable = 0 };
static constexpr int NumLowBitsAvailable = 0;
};
} // namespace llvm

View file

@ -209,9 +209,7 @@ public:
void dump() const;
void dumpColor() const;
void dump(const ASTContext &Context) const;
void dump(raw_ostream &OS, const CommandTraits *Traits,
const SourceManager *SM) const;
void dump(raw_ostream &OS, const ASTContext &Context) const;
SourceRange getSourceRange() const LLVM_READONLY { return Range; }

View file

@ -87,6 +87,7 @@ def P : InlineCommand<"p">;
def A : InlineCommand<"a">;
def E : InlineCommand<"e">;
def Em : InlineCommand<"em">;
def Ref : InlineCommand<"ref">;
def Anchor : InlineCommand<"anchor">;
//===----------------------------------------------------------------------===//
@ -205,7 +206,6 @@ def Paragraph : VerbatimLineCommand<"paragraph">;
def Mainpage : VerbatimLineCommand<"mainpage">;
def Subpage : VerbatimLineCommand<"subpage">;
def Ref : VerbatimLineCommand<"ref">;
def Relates : VerbatimLineCommand<"relates">;
def Related : VerbatimLineCommand<"related">;

View file

@ -217,6 +217,9 @@ public:
bool isTemplateOrSpecialization();
bool isRecordLikeDecl();
bool isClassOrStructDecl();
/// \return \c true if the declaration that this comment is attached to
/// declares either struct, class or tag typedef.
bool isClassOrStructOrTagTypedefDecl();
bool isUnionDecl();
bool isObjCInterfaceDecl();
bool isObjCProtocolDecl();

View file

@ -0,0 +1,194 @@
//===--- ComputeDependence.h -------------------------------------- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Calculate various template dependency flags for the AST.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMPUTE_DEPENDENCE_H
#define LLVM_CLANG_AST_COMPUTE_DEPENDENCE_H
#include "clang/AST/DependenceFlags.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "llvm/ADT/ArrayRef.h"
namespace clang {
class ASTContext;
class Expr;
class FullExpr;
class OpaqueValueExpr;
class ParenExpr;
class UnaryOperator;
class UnaryExprOrTypeTraitExpr;
class ArraySubscriptExpr;
class MatrixSubscriptExpr;
class CompoundLiteralExpr;
class CastExpr;
class BinaryOperator;
class ConditionalOperator;
class BinaryConditionalOperator;
class StmtExpr;
class ConvertVectorExpr;
class VAArgExpr;
class ChooseExpr;
class NoInitExpr;
class ArrayInitLoopExpr;
class ImplicitValueInitExpr;
class InitListExpr;
class ExtVectorElementExpr;
class BlockExpr;
class AsTypeExpr;
class DeclRefExpr;
class RecoveryExpr;
class CXXRewrittenBinaryOperator;
class CXXStdInitializerListExpr;
class CXXTypeidExpr;
class MSPropertyRefExpr;
class MSPropertySubscriptExpr;
class CXXUuidofExpr;
class CXXThisExpr;
class CXXThrowExpr;
class CXXBindTemporaryExpr;
class CXXScalarValueInitExpr;
class CXXDeleteExpr;
class ArrayTypeTraitExpr;
class ExpressionTraitExpr;
class CXXNoexceptExpr;
class PackExpansionExpr;
class SubstNonTypeTemplateParmExpr;
class CoroutineSuspendExpr;
class DependentCoawaitExpr;
class CXXNewExpr;
class CXXPseudoDestructorExpr;
class OverloadExpr;
class DependentScopeDeclRefExpr;
class CXXConstructExpr;
class LambdaExpr;
class CXXUnresolvedConstructExpr;
class CXXDependentScopeMemberExpr;
class MaterializeTemporaryExpr;
class CXXFoldExpr;
class TypeTraitExpr;
class ConceptSpecializationExpr;
class PredefinedExpr;
class CallExpr;
class OffsetOfExpr;
class MemberExpr;
class ShuffleVectorExpr;
class GenericSelectionExpr;
class DesignatedInitExpr;
class ParenListExpr;
class PseudoObjectExpr;
class AtomicExpr;
class OMPArraySectionExpr;
class OMPArrayShapingExpr;
class OMPIteratorExpr;
class ObjCArrayLiteral;
class ObjCDictionaryLiteral;
class ObjCBoxedExpr;
class ObjCEncodeExpr;
class ObjCIvarRefExpr;
class ObjCPropertyRefExpr;
class ObjCSubscriptRefExpr;
class ObjCIsaExpr;
class ObjCIndirectCopyRestoreExpr;
class ObjCMessageExpr;
// The following functions are called from constructors of `Expr`, so they
// should not access anything beyond basic
ExprDependence computeDependence(FullExpr *E);
ExprDependence computeDependence(OpaqueValueExpr *E);
ExprDependence computeDependence(ParenExpr *E);
ExprDependence computeDependence(UnaryOperator *E);
ExprDependence computeDependence(UnaryExprOrTypeTraitExpr *E);
ExprDependence computeDependence(ArraySubscriptExpr *E);
ExprDependence computeDependence(MatrixSubscriptExpr *E);
ExprDependence computeDependence(CompoundLiteralExpr *E);
ExprDependence computeDependence(CastExpr *E);
ExprDependence computeDependence(BinaryOperator *E);
ExprDependence computeDependence(ConditionalOperator *E);
ExprDependence computeDependence(BinaryConditionalOperator *E);
ExprDependence computeDependence(StmtExpr *E, unsigned TemplateDepth);
ExprDependence computeDependence(ConvertVectorExpr *E);
ExprDependence computeDependence(VAArgExpr *E);
ExprDependence computeDependence(ChooseExpr *E);
ExprDependence computeDependence(NoInitExpr *E);
ExprDependence computeDependence(ArrayInitLoopExpr *E);
ExprDependence computeDependence(ImplicitValueInitExpr *E);
ExprDependence computeDependence(InitListExpr *E);
ExprDependence computeDependence(ExtVectorElementExpr *E);
ExprDependence computeDependence(BlockExpr *E);
ExprDependence computeDependence(AsTypeExpr *E);
ExprDependence computeDependence(DeclRefExpr *E, const ASTContext &Ctx);
ExprDependence computeDependence(RecoveryExpr *E);
ExprDependence computeDependence(CXXRewrittenBinaryOperator *E);
ExprDependence computeDependence(CXXStdInitializerListExpr *E);
ExprDependence computeDependence(CXXTypeidExpr *E);
ExprDependence computeDependence(MSPropertyRefExpr *E);
ExprDependence computeDependence(MSPropertySubscriptExpr *E);
ExprDependence computeDependence(CXXUuidofExpr *E);
ExprDependence computeDependence(CXXThisExpr *E);
ExprDependence computeDependence(CXXThrowExpr *E);
ExprDependence computeDependence(CXXBindTemporaryExpr *E);
ExprDependence computeDependence(CXXScalarValueInitExpr *E);
ExprDependence computeDependence(CXXDeleteExpr *E);
ExprDependence computeDependence(ArrayTypeTraitExpr *E);
ExprDependence computeDependence(ExpressionTraitExpr *E);
ExprDependence computeDependence(CXXNoexceptExpr *E, CanThrowResult CT);
ExprDependence computeDependence(PackExpansionExpr *E);
ExprDependence computeDependence(SubstNonTypeTemplateParmExpr *E);
ExprDependence computeDependence(CoroutineSuspendExpr *E);
ExprDependence computeDependence(DependentCoawaitExpr *E);
ExprDependence computeDependence(CXXNewExpr *E);
ExprDependence computeDependence(CXXPseudoDestructorExpr *E);
ExprDependence computeDependence(OverloadExpr *E, bool KnownDependent,
bool KnownInstantiationDependent,
bool KnownContainsUnexpandedParameterPack);
ExprDependence computeDependence(DependentScopeDeclRefExpr *E);
ExprDependence computeDependence(CXXConstructExpr *E);
ExprDependence computeDependence(LambdaExpr *E,
bool ContainsUnexpandedParameterPack);
ExprDependence computeDependence(CXXUnresolvedConstructExpr *E);
ExprDependence computeDependence(CXXDependentScopeMemberExpr *E);
ExprDependence computeDependence(MaterializeTemporaryExpr *E);
ExprDependence computeDependence(CXXFoldExpr *E);
ExprDependence computeDependence(TypeTraitExpr *E);
ExprDependence computeDependence(ConceptSpecializationExpr *E,
bool ValueDependent);
ExprDependence computeDependence(PredefinedExpr *E);
ExprDependence computeDependence(CallExpr *E, llvm::ArrayRef<Expr *> PreArgs);
ExprDependence computeDependence(OffsetOfExpr *E);
ExprDependence computeDependence(MemberExpr *E);
ExprDependence computeDependence(ShuffleVectorExpr *E);
ExprDependence computeDependence(GenericSelectionExpr *E,
bool ContainsUnexpandedPack);
ExprDependence computeDependence(DesignatedInitExpr *E);
ExprDependence computeDependence(ParenListExpr *E);
ExprDependence computeDependence(PseudoObjectExpr *E);
ExprDependence computeDependence(AtomicExpr *E);
ExprDependence computeDependence(OMPArraySectionExpr *E);
ExprDependence computeDependence(OMPArrayShapingExpr *E);
ExprDependence computeDependence(OMPIteratorExpr *E);
ExprDependence computeDependence(ObjCArrayLiteral *E);
ExprDependence computeDependence(ObjCDictionaryLiteral *E);
ExprDependence computeDependence(ObjCBoxedExpr *E);
ExprDependence computeDependence(ObjCEncodeExpr *E);
ExprDependence computeDependence(ObjCIvarRefExpr *E);
ExprDependence computeDependence(ObjCPropertyRefExpr *E);
ExprDependence computeDependence(ObjCSubscriptRefExpr *E);
ExprDependence computeDependence(ObjCIsaExpr *E);
ExprDependence computeDependence(ObjCIndirectCopyRestoreExpr *E);
ExprDependence computeDependence(ObjCMessageExpr *E);
} // namespace clang
#endif

View file

@ -50,10 +50,9 @@ template <class T> void addDataToConsumer(T &DataConsumer, const QualType &QT) {
}
template <class T, class Type>
typename std::enable_if<
std::is_integral<Type>::value || std::is_enum<Type>::value ||
std::is_convertible<Type, size_t>::value // for llvm::hash_code
>::type
std::enable_if_t<std::is_integral<Type>::value || std::is_enum<Type>::value ||
std::is_convertible<Type, size_t>::value // for llvm::hash_code
>
addDataToConsumer(T &DataConsumer, Type Data) {
DataConsumer.update(StringRef(reinterpret_cast<char *>(&Data), sizeof(Data)));
}

View file

@ -2030,7 +2030,7 @@ public:
/// declaration to the declaration that is a definition (if there is one).
bool isDefined(const FunctionDecl *&Definition) const;
virtual bool isDefined() const {
bool isDefined() const {
const FunctionDecl* Definition;
return isDefined(Definition);
}
@ -2125,19 +2125,17 @@ public:
bool isTrivialForCall() const { return FunctionDeclBits.IsTrivialForCall; }
void setTrivialForCall(bool IT) { FunctionDeclBits.IsTrivialForCall = IT; }
/// Whether this function is defaulted per C++0x. Only valid for
/// special member functions.
/// Whether this function is defaulted. Valid for e.g.
/// special member functions, defaulted comparisions (not methods!).
bool isDefaulted() const { return FunctionDeclBits.IsDefaulted; }
void setDefaulted(bool D = true) { FunctionDeclBits.IsDefaulted = D; }
/// Whether this function is explicitly defaulted per C++0x. Only valid
/// for special member functions.
/// Whether this function is explicitly defaulted.
bool isExplicitlyDefaulted() const {
return FunctionDeclBits.IsExplicitlyDefaulted;
}
/// State that this function is explicitly defaulted per C++0x. Only valid
/// for special member functions.
/// State that this function is explicitly defaulted.
void setExplicitlyDefaulted(bool ED = true) {
FunctionDeclBits.IsExplicitlyDefaulted = ED;
}
@ -2306,8 +2304,13 @@ public:
/// allocation function. [...]
///
/// If this function is an aligned allocation/deallocation function, return
/// true through IsAligned.
bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;
/// the parameter number of the requested alignment through AlignmentParam.
///
/// If this function is an allocation/deallocation function that takes
/// the `std::nothrow_t` tag, return true through IsNothrow,
bool isReplaceableGlobalAllocationFunction(
Optional<unsigned> *AlignmentParam = nullptr,
bool *IsNothrow = nullptr) const;
/// Determine if this function provides an inline implementation of a builtin.
bool isInlineBuiltinDeclaration() const;
@ -2436,6 +2439,14 @@ public:
/// parameters have default arguments (in C++).
unsigned getMinRequiredArguments() const;
/// Determine whether this function has a single parameter, or multiple
/// parameters where all but the first have default arguments.
///
/// This notion is used in the definition of copy/move constructors and
/// initializer list constructors. Note that, unlike getMinRequiredArguments,
/// parameter packs are not treated specially here.
bool hasOneParamOrDefaultArgs() const;
/// Find the source location information for how the type of this function
/// was written. May be absent (for example if the function was declared via
/// a typedef) and may contain a different type from that of the function
@ -2607,7 +2618,13 @@ public:
/// Retrieve the function declaration from which this function could
/// be instantiated, if it is an instantiation (rather than a non-template
/// or a specialization, for example).
FunctionDecl *getTemplateInstantiationPattern() const;
///
/// If \p ForDefinition is \c false, explicit specializations will be treated
/// as if they were implicit instantiations. This will then find the pattern
/// corresponding to non-definition portions of the declaration, such as
/// default arguments and the exception specification.
FunctionDecl *
getTemplateInstantiationPattern(bool ForDefinition = true) const;
/// Retrieve the primary template that this function template
/// specialization either specializes or was instantiated from.
@ -2915,12 +2932,15 @@ public:
/// Returns the parent of this field declaration, which
/// is the struct in which this field is defined.
///
/// Returns null if this is not a normal class/struct field declaration, e.g.
/// ObjCAtDefsFieldDecl, ObjCIvarDecl.
const RecordDecl *getParent() const {
return cast<RecordDecl>(getDeclContext());
return dyn_cast<RecordDecl>(getDeclContext());
}
RecordDecl *getParent() {
return cast<RecordDecl>(getDeclContext());
return dyn_cast<RecordDecl>(getDeclContext());
}
SourceRange getSourceRange() const override LLVM_READONLY;
@ -3534,6 +3554,7 @@ class EnumDecl : public TagDecl {
/// negative enumerators of this enum. (see getNumNegativeBits)
void setNumNegativeBits(unsigned Num) { EnumDeclBits.NumNegativeBits = Num; }
public:
/// True if this tag declaration is a scoped enumeration. Only
/// possible in C++11 mode.
void setScoped(bool Scoped = true) { EnumDeclBits.IsScoped = Scoped; }
@ -3550,6 +3571,7 @@ class EnumDecl : public TagDecl {
/// Microsoft-style enumeration with a fixed underlying type.
void setFixed(bool Fixed = true) { EnumDeclBits.IsFixed = Fixed; }
private:
/// True if a valid hash is stored in ODRHash.
bool hasODRHash() const { return EnumDeclBits.HasODRHash; }
void setHasODRHash(bool Hash = true) { EnumDeclBits.HasODRHash = Hash; }
@ -3954,6 +3976,11 @@ public:
return cast_or_null<RecordDecl>(TagDecl::getDefinition());
}
/// Returns whether this record is a union, or contains (at any nesting level)
/// a union member. This is used by CMSE to warn about possible information
/// leaks.
bool isOrContainsUnion() const;
// Iterator access to field members. The field iterator only visits
// the non-static data members of this class, ignoring any static
// data members, functions, constructors, destructors, etc.
@ -4335,17 +4362,18 @@ class ImportDecl final : public Decl,
friend class ASTReader;
friend TrailingObjects;
/// The imported module, along with a bit that indicates whether
/// we have source-location information for each identifier in the module
/// name.
///
/// When the bit is false, we only have a single source location for the
/// end of the import declaration.
llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete;
/// The imported module.
Module *ImportedModule = nullptr;
/// The next import in the list of imports local to the translation
/// unit being parsed (not loaded from an AST file).
ImportDecl *NextLocalImport = nullptr;
///
/// Includes a bit that indicates whether we have source-location information
/// for each identifier in the module name.
///
/// When the bit is false, we only have a single source location for the
/// end of the import declaration.
llvm::PointerIntPair<ImportDecl *, 1, bool> NextLocalImportAndComplete;
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs);
@ -4355,6 +4383,20 @@ class ImportDecl final : public Decl,
ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {}
bool isImportComplete() const { return NextLocalImportAndComplete.getInt(); }
void setImportComplete(bool C) { NextLocalImportAndComplete.setInt(C); }
/// The next import in the list of imports local to the translation
/// unit being parsed (not loaded from an AST file).
ImportDecl *getNextLocalImport() const {
return NextLocalImportAndComplete.getPointer();
}
void setNextLocalImport(ImportDecl *Import) {
NextLocalImportAndComplete.setPointer(Import);
}
public:
/// Create a new module import declaration.
static ImportDecl *Create(ASTContext &C, DeclContext *DC,
@ -4372,7 +4414,7 @@ public:
unsigned NumLocations);
/// Retrieve the module that was imported by the import declaration.
Module *getImportedModule() const { return ImportedAndComplete.getPointer(); }
Module *getImportedModule() const { return ImportedModule; }
/// Retrieves the locations of each of the identifiers that make up
/// the complete module name in the import declaration.
@ -4520,6 +4562,13 @@ inline bool IsEnumDeclScoped(EnumDecl *ED) {
return ED->isScoped();
}
/// OpenMP variants are mangled early based on their OpenMP context selector.
/// The new name looks likes this:
/// <name> + OpenMPVariantManglingSeparatorStr + <mangled OpenMP context>
static constexpr StringRef getOpenMPVariantManglingSeparatorStr() {
return "$ompvariant";
}
} // namespace clang
#endif // LLVM_CLANG_AST_DECL_H

View file

@ -66,6 +66,7 @@ class SourceManager;
class Stmt;
class StoredDeclsMap;
class TemplateDecl;
class TemplateParameterList;
class TranslationUnitDecl;
class UsingDirectiveDecl;
@ -465,6 +466,10 @@ public:
ASTContext &getASTContext() const LLVM_READONLY;
/// Helper to get the language options from the ASTContext.
/// Defined out of line to avoid depending on ASTContext.h.
const LangOptions &getLangOpts() const LLVM_READONLY;
void setAccess(AccessSpecifier AS) {
Access = AS;
assert(AccessDeclContextSanity());
@ -514,7 +519,7 @@ public:
if (!HasAttrs) return;
AttrVec &Vec = getAttrs();
Vec.erase(std::remove_if(Vec.begin(), Vec.end(), isa<T, Attr*>), Vec.end());
llvm::erase_if(Vec, [](Attr *A) { return isa<T>(A); });
if (Vec.empty())
HasAttrs = false;
@ -626,7 +631,16 @@ protected:
setModuleOwnershipKind(ModuleOwnershipKind::ModulePrivate);
}
/// Set the owning module ID.
public:
/// Set the FromASTFile flag. This indicates that this declaration
/// was deserialized and not parsed from source code and enables
/// features such as module ownership information.
void setFromASTFile() {
FromASTFile = true;
}
/// Set the owning module ID. This may only be called for
/// deserialized Decls.
void setOwningModuleID(unsigned ID) {
assert(isFromASTFile() && "Only works on a deserialized declaration");
*((unsigned*)this - 2) = ID;
@ -767,18 +781,19 @@ public:
/// all declarations in a global module fragment are unowned.
Module *getOwningModuleForLinkage(bool IgnoreLinkage = false) const;
/// Determine whether this declaration might be hidden from name
/// lookup. Note that the declaration might be visible even if this returns
/// \c false, if the owning module is visible within the query context.
// FIXME: Rename this to make it clearer what it does.
bool isHidden() const {
return (int)getModuleOwnershipKind() > (int)ModuleOwnershipKind::Visible;
/// Determine whether this declaration is definitely visible to name lookup,
/// independent of whether the owning module is visible.
/// Note: The declaration may be visible even if this returns \c false if the
/// owning module is visible within the query context. This is a low-level
/// helper function; most code should be calling Sema::isVisible() instead.
bool isUnconditionallyVisible() const {
return (int)getModuleOwnershipKind() <= (int)ModuleOwnershipKind::Visible;
}
/// Set that this declaration is globally visible, even if it came from a
/// module that is not visible.
void setVisibleDespiteOwningModule() {
if (isHidden())
if (!isUnconditionallyVisible())
setModuleOwnershipKind(ModuleOwnershipKind::Visible);
}
@ -848,6 +863,10 @@ public:
// within the scope of a template parameter).
bool isTemplated() const;
/// Determine the number of levels of template parameter surrounding this
/// declaration.
unsigned getTemplateDepth() const;
/// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
/// scoped decl is defined outside the current function or method. This is
/// roughly global variables and functions, but also handles enums (which
@ -856,15 +875,19 @@ public:
return getParentFunctionOrMethod() == nullptr;
}
/// Returns true if this declaration is lexically inside a function or inside
/// a variable initializer. It recognizes non-defining declarations as well
/// as members of local classes:
/// Determine whether a substitution into this declaration would occur as
/// part of a substitution into a dependent local scope. Such a substitution
/// transitively substitutes into all constructs nested within this
/// declaration.
///
/// This recognizes non-defining declarations as well as members of local
/// classes and lambdas:
/// \code
/// void foo() { void bar(); }
/// void foo2() { class ABC { void bar(); }; }
/// inline int x = [](){ return 0; };
/// template<typename T> void foo() { void bar(); }
/// template<typename T> void foo2() { class ABC { void bar(); }; }
/// template<typename T> inline int x = [](){ return 0; }();
/// \endcode
bool isInLocalScope() const;
bool isInLocalScopeForInstantiation() const;
/// If this decl is defined inside a function/method/block it returns
/// the corresponding DeclContext, otherwise it returns null.
@ -1024,8 +1047,16 @@ public:
/// If this is a declaration that describes some template, this
/// method returns that template declaration.
///
/// Note that this returns nullptr for partial specializations, because they
/// are not modeled as TemplateDecls. Use getDescribedTemplateParams to handle
/// those cases.
TemplateDecl *getDescribedTemplate() const;
/// If this is a declaration that describes some template or partial
/// specialization, this returns the corresponding template parameter list.
const TemplateParameterList *getDescribedTemplateParams() const;
/// Returns the function itself, or the templated function if this is a
/// function template.
FunctionDecl *getAsFunction() LLVM_READONLY;
@ -1729,30 +1760,30 @@ protected:
ObjCContainerDeclBitfields ObjCContainerDeclBits;
LinkageSpecDeclBitfields LinkageSpecDeclBits;
BlockDeclBitfields BlockDeclBits;
};
static_assert(sizeof(DeclContextBitfields) <= 8,
"DeclContextBitfields is larger than 8 bytes!");
static_assert(sizeof(TagDeclBitfields) <= 8,
"TagDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(EnumDeclBitfields) <= 8,
"EnumDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(RecordDeclBitfields) <= 8,
"RecordDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(OMPDeclareReductionDeclBitfields) <= 8,
"OMPDeclareReductionDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(FunctionDeclBitfields) <= 8,
"FunctionDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(CXXConstructorDeclBitfields) <= 8,
"CXXConstructorDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(ObjCMethodDeclBitfields) <= 8,
"ObjCMethodDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(ObjCContainerDeclBitfields) <= 8,
"ObjCContainerDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(LinkageSpecDeclBitfields) <= 8,
"LinkageSpecDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(BlockDeclBitfields) <= 8,
"BlockDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(DeclContextBitfields) <= 8,
"DeclContextBitfields is larger than 8 bytes!");
static_assert(sizeof(TagDeclBitfields) <= 8,
"TagDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(EnumDeclBitfields) <= 8,
"EnumDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(RecordDeclBitfields) <= 8,
"RecordDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(OMPDeclareReductionDeclBitfields) <= 8,
"OMPDeclareReductionDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(FunctionDeclBitfields) <= 8,
"FunctionDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(CXXConstructorDeclBitfields) <= 8,
"CXXConstructorDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(ObjCMethodDeclBitfields) <= 8,
"ObjCMethodDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(ObjCContainerDeclBitfields) <= 8,
"ObjCContainerDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(LinkageSpecDeclBitfields) <= 8,
"LinkageSpecDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(BlockDeclBitfields) <= 8,
"BlockDeclBitfields is larger than 8 bytes!");
};
/// FirstDecl - The first declaration stored within this declaration
/// context.

View file

@ -15,7 +15,6 @@
#ifndef LLVM_CLANG_AST_DECLCXX_H
#define LLVM_CLANG_AST_DECLCXX_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
@ -40,6 +39,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
@ -53,6 +53,7 @@
namespace clang {
class ASTContext;
class ClassTemplateDecl;
class ConstructorUsingShadowDecl;
class CXXBasePath;
@ -711,6 +712,13 @@ public:
!data().DefaultedMoveConstructorIsDeleted;
}
/// \c true if we know for sure that this class has a single,
/// accessible, unambiguous copy assignment operator that is not deleted.
bool hasSimpleCopyAssignment() const {
return !hasUserDeclaredCopyAssignment() &&
!data().DefaultedCopyAssignmentIsDeleted;
}
/// \c true if we know for sure that this class has a single,
/// accessible, unambiguous move assignment operator that is not deleted.
bool hasSimpleMoveAssignment() const {
@ -871,6 +879,15 @@ public:
return data().UserDeclaredSpecialMembers & SMF_CopyAssignment;
}
/// Set that we attempted to declare an implicit copy assignment
/// operator, but overload resolution failed so we deleted it.
void setImplicitCopyAssignmentIsDeleted() {
assert((data().DefaultedCopyAssignmentIsDeleted ||
needsOverloadResolutionForCopyAssignment()) &&
"copy assignment should not be deleted");
data().DefaultedCopyAssignmentIsDeleted = true;
}
/// Determine whether this class needs an implicit copy
/// assignment operator to be lazily declared.
bool needsImplicitCopyAssignment() const {
@ -880,7 +897,16 @@ public:
/// Determine whether we need to eagerly declare a defaulted copy
/// assignment operator for this class.
bool needsOverloadResolutionForCopyAssignment() const {
return data().HasMutableFields;
// C++20 [class.copy.assign]p2:
// If the class definition declares a move constructor or move assignment
// operator, the implicitly declared copy assignment operator is defined
// as deleted.
// In MSVC mode, sometimes a declared move constructor does not delete an
// implicit copy assignment, so defer this choice to Sema.
if (data().UserDeclaredSpecialMembers &
(SMF_MoveConstructor | SMF_MoveAssignment))
return true;
return data().NeedOverloadResolutionForCopyAssignment;
}
/// Determine whether an implicit copy assignment operator for this
@ -998,6 +1024,9 @@ public:
return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault);
}
/// Set the captures for this lambda closure type.
void setCaptures(ArrayRef<LambdaCapture> Captures);
/// For a closure type, retrieve the mapping from captured
/// variables and \c this to the non-static data members that store the
/// values or references of the captures.
@ -1029,6 +1058,8 @@ public:
: nullptr;
}
unsigned capture_size() const { return getLambdaData().NumCaptures; }
using conversion_iterator = UnresolvedSetIterator;
conversion_iterator conversion_begin() const {
@ -1166,7 +1197,7 @@ public:
bool defaultedDefaultConstructorIsConstexpr() const {
return data().DefaultedDefaultConstructorIsConstexpr &&
(!isUnion() || hasInClassInitializer() || !hasVariantMembers() ||
getASTContext().getLangOpts().CPlusPlus2a);
getLangOpts().CPlusPlus20);
}
/// Determine whether this class has a constexpr default constructor.
@ -1258,7 +1289,7 @@ public:
/// would be constexpr.
bool defaultedDestructorIsConstexpr() const {
return data().DefaultedDestructorIsConstexpr &&
getASTContext().getLangOpts().CPlusPlus2a;
getLangOpts().CPlusPlus20;
}
/// Determine whether this class has a constexpr destructor.
@ -1355,10 +1386,10 @@ public:
///
/// Only in C++17 and beyond, are lambdas literal types.
bool isLiteral() const {
ASTContext &Ctx = getASTContext();
return (Ctx.getLangOpts().CPlusPlus2a ? hasConstexprDestructor()
const LangOptions &LangOpts = getLangOpts();
return (LangOpts.CPlusPlus20 ? hasConstexprDestructor()
: hasTrivialDestructor()) &&
(!isLambda() || Ctx.getLangOpts().CPlusPlus17) &&
(!isLambda() || LangOpts.CPlusPlus17) &&
!hasNonLiteralTypeFieldsOrBases() &&
(isAggregate() || isLambda() ||
hasConstexprNonCopyMoveConstructor() ||
@ -1517,14 +1548,8 @@ public:
/// returns false if the class has non-computable base classes.
///
/// \param BaseMatches Callback invoked for each (direct or indirect) base
/// class of this type, or if \p AllowShortCircuit is true then until a call
/// returns false.
///
/// \param AllowShortCircuit if false, forces the callback to be called
/// for every base class, even if a dependent or non-matching base was
/// found.
bool forallBases(ForallBasesCallback BaseMatches,
bool AllowShortCircuit = true) const;
/// class of this type until a call returns false.
bool forallBases(ForallBasesCallback BaseMatches) const;
/// Function type used by lookupInBases() to determine whether a
/// specific base class subobject matches the lookup criteria.
@ -1696,6 +1721,10 @@ public:
/// actually abstract.
bool mayBeAbstract() const;
/// Determine whether it's impossible for a class to be derived from this
/// class. This is best-effort, and may conservatively return false.
bool isEffectivelyFinal() const;
/// If this is the closure type of a lambda expression, retrieve the
/// number to be used for name mangling in the Itanium C++ ABI.
///
@ -2037,7 +2066,8 @@ public:
method_iterator end_overridden_methods() const;
unsigned size_overridden_methods() const;
using overridden_method_range= ASTContext::overridden_method_range;
using overridden_method_range = llvm::iterator_range<
llvm::TinyPtrVector<const CXXMethodDecl *>::const_iterator>;
overridden_method_range overridden_methods() const;
@ -2417,17 +2447,6 @@ class CXXConstructorDecl final
: ExplicitSpecKind::ResolvedFalse);
}
void setExplicitSpecifier(ExplicitSpecifier ES) {
assert((!ES.getExpr() ||
CXXConstructorDeclBits.HasTrailingExplicitSpecifier) &&
"cannot set this explicit specifier. no trail-allocated space for "
"explicit");
if (ES.getExpr())
*getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>() = ES;
else
CXXConstructorDeclBits.IsSimpleExplicit = ES.isExplicit();
}
enum TraillingAllocKind {
TAKInheritsConstructor = 1,
TAKHasTailExplicit = 1 << 1,
@ -2453,6 +2472,17 @@ public:
InheritedConstructor Inherited = InheritedConstructor(),
Expr *TrailingRequiresClause = nullptr);
void setExplicitSpecifier(ExplicitSpecifier ES) {
assert((!ES.getExpr() ||
CXXConstructorDeclBits.HasTrailingExplicitSpecifier) &&
"cannot set this explicit specifier. no trail-allocated space for "
"explicit");
if (ES.getExpr())
*getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>() = ES;
else
CXXConstructorDeclBits.IsSimpleExplicit = ES.isExplicit();
}
ExplicitSpecifier getExplicitSpecifier() {
return getCanonicalDecl()->getExplicitSpecifierInternal();
}
@ -2724,8 +2754,6 @@ class CXXConversionDecl : public CXXMethodDecl {
ExplicitSpecifier ExplicitSpec;
void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
@ -2747,6 +2775,7 @@ public:
/// Return true if the declartion is already resolved to be explicit.
bool isExplicit() const { return getExplicitSpecifier().isExplicit(); }
void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; }
/// Returns the type that this conversion function is converting to.
QualType getConversionType() const {
@ -3964,6 +3993,81 @@ public:
IdentifierInfo* getSetterId() const { return SetterId; }
};
/// Parts of a decomposed MSGuidDecl. Factored out to avoid unnecessary
/// dependencies on DeclCXX.h.
struct MSGuidDeclParts {
/// {01234567-...
uint32_t Part1;
/// ...-89ab-...
uint16_t Part2;
/// ...-cdef-...
uint16_t Part3;
/// ...-0123-456789abcdef}
uint8_t Part4And5[8];
uint64_t getPart4And5AsUint64() const {
uint64_t Val;
memcpy(&Val, &Part4And5, sizeof(Part4And5));
return Val;
}
};
/// A global _GUID constant. These are implicitly created by UuidAttrs.
///
/// struct _declspec(uuid("01234567-89ab-cdef-0123-456789abcdef")) X{};
///
/// X is a CXXRecordDecl that contains a UuidAttr that references the (unique)
/// MSGuidDecl for the specified UUID.
class MSGuidDecl : public ValueDecl,
public Mergeable<MSGuidDecl>,
public llvm::FoldingSetNode {
public:
using Parts = MSGuidDeclParts;
private:
/// The decomposed form of the UUID.
Parts PartVal;
/// The resolved value of the UUID as an APValue. Computed on demand and
/// cached.
mutable APValue APVal;
void anchor() override;
MSGuidDecl(DeclContext *DC, QualType T, Parts P);
static MSGuidDecl *Create(const ASTContext &C, QualType T, Parts P);
static MSGuidDecl *CreateDeserialized(ASTContext &C, unsigned ID);
// Only ASTContext::getMSGuidDecl and deserialization create these.
friend class ASTContext;
friend class ASTReader;
friend class ASTDeclReader;
public:
/// Print this UUID in a human-readable format.
void printName(llvm::raw_ostream &OS) const override;
/// Get the decomposed parts of this declaration.
Parts getParts() const { return PartVal; }
/// Get the value of this MSGuidDecl as an APValue. This may fail and return
/// an absent APValue if the type of the declaration is not of the expected
/// shape.
APValue &getAsAPValue() const;
static void Profile(llvm::FoldingSetNodeID &ID, Parts P) {
ID.AddInteger(P.Part1);
ID.AddInteger(P.Part2);
ID.AddInteger(P.Part3);
ID.AddInteger(P.getPart4And5AsUint64());
}
void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, PartVal); }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::MSGuid; }
};
/// Insertion operator for diagnostics. This allows sending an AccessSpecifier
/// into a diagnostic with <<.
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,

View file

@ -147,7 +147,7 @@ namespace llvm {
return clang::DeclGroupRef::getFromOpaquePtr(P);
}
enum { NumLowBitsAvailable = 0 };
static constexpr int NumLowBitsAvailable = 0;
};
} // namespace llvm

View file

@ -15,6 +15,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjCCommon.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/SelectorLocationsKind.h"
@ -402,7 +403,7 @@ public:
}
/// createImplicitParams - Used to lazily create the self and cmd
/// implict parameters. This must be called prior to using getSelfDecl()
/// implicit parameters. This must be called prior to using getSelfDecl()
/// or getCmdDecl(). The call is ignored if the implicit parameters
/// have already been created.
void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
@ -742,34 +743,6 @@ class ObjCPropertyDecl : public NamedDecl {
void anchor() override;
public:
enum PropertyAttributeKind {
OBJC_PR_noattr = 0x00,
OBJC_PR_readonly = 0x01,
OBJC_PR_getter = 0x02,
OBJC_PR_assign = 0x04,
OBJC_PR_readwrite = 0x08,
OBJC_PR_retain = 0x10,
OBJC_PR_copy = 0x20,
OBJC_PR_nonatomic = 0x40,
OBJC_PR_setter = 0x80,
OBJC_PR_atomic = 0x100,
OBJC_PR_weak = 0x200,
OBJC_PR_strong = 0x400,
OBJC_PR_unsafe_unretained = 0x800,
/// Indicates that the nullability of the type was spelled with a
/// property attribute rather than a type qualifier.
OBJC_PR_nullability = 0x1000,
OBJC_PR_null_resettable = 0x2000,
OBJC_PR_class = 0x4000,
OBJC_PR_direct = 0x8000
// Adding a property should change NumPropertyAttrsBits
};
enum {
/// Number of bits fitting all the property attributes.
NumPropertyAttrsBits = 16
};
enum SetterKind { Assign, Retain, Copy, Weak };
enum PropertyControl { None, Required, Optional };
@ -782,8 +755,8 @@ private:
QualType DeclType;
TypeSourceInfo *DeclTypeSourceInfo;
unsigned PropertyAttributes : NumPropertyAttrsBits;
unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits;
unsigned PropertyAttributes : NumObjCPropertyAttrsBits;
unsigned PropertyAttributesAsWritten : NumObjCPropertyAttrsBits;
// \@required/\@optional
unsigned PropertyImplementation : 2;
@ -810,15 +783,14 @@ private:
ObjCIvarDecl *PropertyIvarDecl = nullptr;
ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
SourceLocation AtLocation, SourceLocation LParenLocation,
QualType T, TypeSourceInfo *TSI,
PropertyControl propControl)
: NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI),
PropertyAttributes(OBJC_PR_noattr),
PropertyAttributesAsWritten(OBJC_PR_noattr),
PropertyImplementation(propControl), GetterName(Selector()),
SetterName(Selector()) {}
SourceLocation AtLocation, SourceLocation LParenLocation,
QualType T, TypeSourceInfo *TSI, PropertyControl propControl)
: NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI),
PropertyAttributes(ObjCPropertyAttribute::kind_noattr),
PropertyAttributesAsWritten(ObjCPropertyAttribute::kind_noattr),
PropertyImplementation(propControl), GetterName(Selector()),
SetterName(Selector()) {}
public:
static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
@ -850,11 +822,11 @@ public:
/// type.
QualType getUsageType(QualType objectType) const;
PropertyAttributeKind getPropertyAttributes() const {
return PropertyAttributeKind(PropertyAttributes);
ObjCPropertyAttribute::Kind getPropertyAttributes() const {
return ObjCPropertyAttribute::Kind(PropertyAttributes);
}
void setPropertyAttributes(PropertyAttributeKind PRVal) {
void setPropertyAttributes(ObjCPropertyAttribute::Kind PRVal) {
PropertyAttributes |= PRVal;
}
@ -862,11 +834,11 @@ public:
PropertyAttributes = PRVal;
}
PropertyAttributeKind getPropertyAttributesAsWritten() const {
return PropertyAttributeKind(PropertyAttributesAsWritten);
ObjCPropertyAttribute::Kind getPropertyAttributesAsWritten() const {
return ObjCPropertyAttribute::Kind(PropertyAttributesAsWritten);
}
void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
void setPropertyAttributesAsWritten(ObjCPropertyAttribute::Kind PRVal) {
PropertyAttributesAsWritten = PRVal;
}
@ -874,23 +846,28 @@ public:
/// isReadOnly - Return true iff the property has a setter.
bool isReadOnly() const {
return (PropertyAttributes & OBJC_PR_readonly);
return (PropertyAttributes & ObjCPropertyAttribute::kind_readonly);
}
/// isAtomic - Return true if the property is atomic.
bool isAtomic() const {
return (PropertyAttributes & OBJC_PR_atomic);
return (PropertyAttributes & ObjCPropertyAttribute::kind_atomic);
}
/// isRetaining - Return true if the property retains its value.
bool isRetaining() const {
return (PropertyAttributes &
(OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy));
return (PropertyAttributes & (ObjCPropertyAttribute::kind_retain |
ObjCPropertyAttribute::kind_strong |
ObjCPropertyAttribute::kind_copy));
}
bool isInstanceProperty() const { return !isClassProperty(); }
bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; }
bool isDirectProperty() const { return PropertyAttributes & OBJC_PR_direct; }
bool isClassProperty() const {
return PropertyAttributes & ObjCPropertyAttribute::kind_class;
}
bool isDirectProperty() const {
return PropertyAttributes & ObjCPropertyAttribute::kind_direct;
}
ObjCPropertyQueryKind getQueryKind() const {
return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class :
@ -906,13 +883,13 @@ public:
/// the property setter. This is only valid if the property has been
/// defined to have a setter.
SetterKind getSetterKind() const {
if (PropertyAttributes & OBJC_PR_strong)
if (PropertyAttributes & ObjCPropertyAttribute::kind_strong)
return getType()->isBlockPointerType() ? Copy : Retain;
if (PropertyAttributes & OBJC_PR_retain)
if (PropertyAttributes & ObjCPropertyAttribute::kind_retain)
return Retain;
if (PropertyAttributes & OBJC_PR_copy)
if (PropertyAttributes & ObjCPropertyAttribute::kind_copy)
return Copy;
if (PropertyAttributes & OBJC_PR_weak)
if (PropertyAttributes & ObjCPropertyAttribute::kind_weak)
return Weak;
return Assign;
}
@ -2692,9 +2669,7 @@ public:
/// Get the name of the class associated with this interface.
//
// FIXME: Move to StringRef API.
std::string getNameAsString() const {
return getName();
}
std::string getNameAsString() const { return std::string(getName()); }
/// Produce a name to be used for class's metadata. It comes either via
/// class's objc_runtime_name attribute or class name.
@ -2908,11 +2883,11 @@ ObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() {
}
inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) {
return !Cat->isHidden();
return Cat->isUnconditionallyVisible();
}
inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) {
return Cat->IsClassExtension() && !Cat->isHidden();
return Cat->IsClassExtension() && Cat->isUnconditionallyVisible();
}
inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) {

View file

@ -0,0 +1,55 @@
//===- DeclObjCCommon.h - Classes for representing declarations -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains common ObjC enums and classes used in AST and
// Sema.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLOBJC_COMMON_H
#define LLVM_CLANG_AST_DECLOBJC_COMMON_H
namespace clang {
/// ObjCPropertyAttribute::Kind - list of property attributes.
/// Keep this list in sync with LLVM's Dwarf.h ApplePropertyAttributes.s
namespace ObjCPropertyAttribute {
enum Kind {
kind_noattr = 0x00,
kind_readonly = 0x01,
kind_getter = 0x02,
kind_assign = 0x04,
kind_readwrite = 0x08,
kind_retain = 0x10,
kind_copy = 0x20,
kind_nonatomic = 0x40,
kind_setter = 0x80,
kind_atomic = 0x100,
kind_weak = 0x200,
kind_strong = 0x400,
kind_unsafe_unretained = 0x800,
/// Indicates that the nullability of the type was spelled with a
/// property attribute rather than a type qualifier.
kind_nullability = 0x1000,
kind_null_resettable = 0x2000,
kind_class = 0x4000,
kind_direct = 0x8000,
// Adding a property should change NumObjCPropertyAttrsBits
// Also, don't forget to update the Clang C API at CXObjCPropertyAttrKind and
// clang_Cursor_getObjCPropertyAttributes.
};
} // namespace ObjCPropertyAttribute::Kind
enum {
/// Number of bits fitting all the property attributes.
NumObjCPropertyAttrsBits = 16
};
} // namespace clang
#endif // LLVM_CLANG_AST_DECLOBJC_COMMON_H

View file

@ -129,7 +129,7 @@ private:
/// the declare reduction construct is declared inside compound statement.
LazyDeclPtr PrevDeclInScope;
virtual void anchor();
void anchor() override;
OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, QualType Ty,
@ -228,7 +228,7 @@ class OMPDeclareMapperDecl final : public ValueDecl, public DeclContext {
LazyDeclPtr PrevDeclInScope;
virtual void anchor();
void anchor() override;
OMPDeclareMapperDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, QualType Ty,

View file

@ -1891,6 +1891,10 @@ public:
return *TemplateArgs;
}
void setTemplateArgs(TemplateArgumentList *Args) {
TemplateArgs = Args;
}
/// Determine the kind of specialization that this
/// declaration represents.
TemplateSpecializationKind getSpecializationKind() const {
@ -1923,6 +1927,10 @@ public:
getTemplateSpecializationKind());
}
void setSpecializedTemplate(ClassTemplateDecl *Specialized) {
SpecializedTemplate = Specialized;
}
void setSpecializationKind(TemplateSpecializationKind TSK) {
SpecializationKind = TSK;
}

View file

@ -0,0 +1,284 @@
//===--- DependenceFlags.h ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DEPENDENCEFLAGS_H
#define LLVM_CLANG_AST_DEPENDENCEFLAGS_H
#include "clang/Basic/BitmaskEnum.h"
#include "llvm/ADT/BitmaskEnum.h"
#include <cstdint>
namespace clang {
struct ExprDependenceScope {
enum ExprDependence : uint8_t {
UnexpandedPack = 1,
// This expr depends in any way on
// - a template parameter, it implies that the resolution of this expr may
// cause instantiation to fail
// - or an error (often in a non-template context)
//
// Note that C++ standard doesn't define the instantiation-dependent term,
// we follow the formal definition coming from the Itanium C++ ABI, and
// extend it to errors.
Instantiation = 2,
// The type of this expr depends on a template parameter, or an error.
Type = 4,
// The value of this expr depends on a template parameter, or an error.
Value = 8,
// clang extension: this expr contains or references an error, and is
// considered dependent on how that error is resolved.
Error = 16,
None = 0,
All = 31,
TypeValue = Type | Value,
TypeInstantiation = Type | Instantiation,
ValueInstantiation = Value | Instantiation,
TypeValueInstantiation = Type | Value | Instantiation,
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
};
};
using ExprDependence = ExprDependenceScope::ExprDependence;
struct TypeDependenceScope {
enum TypeDependence : uint8_t {
/// Whether this type contains an unexpanded parameter pack
/// (for C++11 variadic templates)
UnexpandedPack = 1,
/// Whether this type somehow involves
/// - a template parameter, even if the resolution of the type does not
/// depend on a template parameter.
/// - or an error.
Instantiation = 2,
/// Whether this type
/// - is a dependent type (C++ [temp.dep.type])
/// - or it somehow involves an error, e.g. decltype(recovery-expr)
Dependent = 4,
/// Whether this type is a variably-modified type (C99 6.7.5).
VariablyModified = 8,
/// Whether this type references an error, e.g. decltype(err-expression)
/// yields an error type.
Error = 16,
None = 0,
All = 31,
DependentInstantiation = Dependent | Instantiation,
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
};
};
using TypeDependence = TypeDependenceScope::TypeDependence;
#define LLVM_COMMON_DEPENDENCE(NAME) \
struct NAME##Scope { \
enum NAME : uint8_t { \
UnexpandedPack = 1, \
Instantiation = 2, \
Dependent = 4, \
Error = 8, \
\
None = 0, \
DependentInstantiation = Dependent | Instantiation, \
All = 15, \
\
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) \
}; \
}; \
using NAME = NAME##Scope::NAME;
LLVM_COMMON_DEPENDENCE(NestedNameSpecifierDependence)
LLVM_COMMON_DEPENDENCE(TemplateNameDependence)
LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence)
#undef LLVM_COMMON_DEPENDENCE
// A combined space of all dependence concepts for all node types.
// Used when aggregating dependence of nodes of different types.
class Dependence {
public:
enum Bits : uint8_t {
None = 0,
// Contains a template parameter pack that wasn't expanded.
UnexpandedPack = 1,
// Depends on a template parameter or an error in some way.
// Validity depends on how the template is instantiated or the error is
// resolved.
Instantiation = 2,
// Expression type depends on template context, or an error.
// Value and Instantiation should also be set.
Type = 4,
// Expression value depends on template context, or an error.
// Instantiation should also be set.
Value = 8,
// Depends on template context, or an error.
// The type/value distinction is only meaningful for expressions.
Dependent = Type | Value,
// Includes an error, and depends on how it is resolved.
Error = 16,
// Type depends on a runtime value (variable-length array).
VariablyModified = 32,
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
};
Dependence() : V(None) {}
Dependence(TypeDependence D)
: V(translate(D, TypeDependence::UnexpandedPack, UnexpandedPack) |
translate(D, TypeDependence::Instantiation, Instantiation) |
translate(D, TypeDependence::Dependent, Dependent) |
translate(D, TypeDependence::Error, Error) |
translate(D, TypeDependence::VariablyModified, VariablyModified)) {}
Dependence(ExprDependence D)
: V(translate(D, ExprDependence::UnexpandedPack, UnexpandedPack) |
translate(D, ExprDependence::Instantiation, Instantiation) |
translate(D, ExprDependence::Type, Type) |
translate(D, ExprDependence::Value, Value) |
translate(D, ExprDependence::Error, Error)) {}
Dependence(NestedNameSpecifierDependence D) :
V ( translate(D, NNSDependence::UnexpandedPack, UnexpandedPack) |
translate(D, NNSDependence::Instantiation, Instantiation) |
translate(D, NNSDependence::Dependent, Dependent) |
translate(D, NNSDependence::Error, Error)) {}
Dependence(TemplateArgumentDependence D)
: V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) |
translate(D, TADependence::Instantiation, Instantiation) |
translate(D, TADependence::Dependent, Dependent) |
translate(D, TADependence::Error, Error)) {}
Dependence(TemplateNameDependence D)
: V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) |
translate(D, TNDependence::Instantiation, Instantiation) |
translate(D, TNDependence::Dependent, Dependent) |
translate(D, TNDependence::Error, Error)) {}
TypeDependence type() const {
return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
translate(V, Instantiation, TypeDependence::Instantiation) |
translate(V, Dependent, TypeDependence::Dependent) |
translate(V, Error, TypeDependence::Error) |
translate(V, VariablyModified, TypeDependence::VariablyModified);
}
ExprDependence expr() const {
return translate(V, UnexpandedPack, ExprDependence::UnexpandedPack) |
translate(V, Instantiation, ExprDependence::Instantiation) |
translate(V, Type, ExprDependence::Type) |
translate(V, Value, ExprDependence::Value) |
translate(V, Error, ExprDependence::Error);
}
NestedNameSpecifierDependence nestedNameSpecifier() const {
return translate(V, UnexpandedPack, NNSDependence::UnexpandedPack) |
translate(V, Instantiation, NNSDependence::Instantiation) |
translate(V, Dependent, NNSDependence::Dependent) |
translate(V, Error, NNSDependence::Error);
}
TemplateArgumentDependence templateArgument() const {
return translate(V, UnexpandedPack, TADependence::UnexpandedPack) |
translate(V, Instantiation, TADependence::Instantiation) |
translate(V, Dependent, TADependence::Dependent) |
translate(V, Error, TADependence::Error);
}
TemplateNameDependence templateName() const {
return translate(V, UnexpandedPack, TNDependence::UnexpandedPack) |
translate(V, Instantiation, TNDependence::Instantiation) |
translate(V, Dependent, TNDependence::Dependent) |
translate(V, Error, TNDependence::Error);
}
private:
Bits V;
template <typename T, typename U>
static U translate(T Bits, T FromBit, U ToBit) {
return (Bits & FromBit) ? ToBit : static_cast<U>(0);
}
// Abbreviations to make conversions more readable.
using NNSDependence = NestedNameSpecifierDependence;
using TADependence = TemplateArgumentDependence;
using TNDependence = TemplateNameDependence;
};
/// Computes dependencies of a reference with the name having template arguments
/// with \p TA dependencies.
inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
return Dependence(TA).expr();
}
inline ExprDependence toExprDependence(TypeDependence D) {
return Dependence(D).expr();
}
// Note: it's often necessary to strip `Dependent` from qualifiers.
// If V<T>:: refers to the current instantiation, NNS is considered dependent
// but the containing V<T>::foo likely isn't.
inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
return Dependence(D).expr();
}
inline ExprDependence turnTypeToValueDependence(ExprDependence D) {
// Type-dependent expressions are always be value-dependent, so we simply drop
// type dependency.
return D & ~ExprDependence::Type;
}
inline ExprDependence turnValueToTypeDependence(ExprDependence D) {
// Type-dependent expressions are always be value-dependent.
if (D & ExprDependence::Value)
D |= ExprDependence::Type;
return D;
}
// Returned type-dependence will never have VariablyModified set.
inline TypeDependence toTypeDependence(ExprDependence D) {
return Dependence(D).type();
}
inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
return Dependence(D).type();
}
inline TypeDependence toTypeDependence(TemplateNameDependence D) {
return Dependence(D).type();
}
inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
return Dependence(D).type();
}
inline NestedNameSpecifierDependence
toNestedNameSpecifierDependendence(TypeDependence D) {
return Dependence(D).nestedNameSpecifier();
}
inline TemplateArgumentDependence
toTemplateArgumentDependence(TypeDependence D) {
return Dependence(D).templateArgument();
}
inline TemplateArgumentDependence
toTemplateArgumentDependence(TemplateNameDependence D) {
return Dependence(D).templateArgument();
}
inline TemplateArgumentDependence
toTemplateArgumentDependence(ExprDependence D) {
return Dependence(D).templateArgument();
}
inline TemplateNameDependence
toTemplateNameDependence(NestedNameSpecifierDependence D) {
return Dependence(D).templateName();
}
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
} // namespace clang
#endif

File diff suppressed because it is too large Load diff

View file

@ -14,15 +14,19 @@
#ifndef LLVM_CLANG_AST_EXPRCXX_H
#define LLVM_CLANG_AST_EXPRCXX_H
#include "clang/AST/ASTConcept.h"
#include "clang/AST/ComputeDependence.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
@ -80,6 +84,7 @@ class CXXOperatorCallExpr final : public CallExpr {
friend class ASTStmtWriter;
SourceRange Range;
FPOptionsOverride Overrides;
// CXXOperatorCallExpr has some trailing objects belonging
// to CallExpr. See CallExpr for the details.
@ -88,7 +93,7 @@ class CXXOperatorCallExpr final : public CallExpr {
CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
SourceLocation OperatorLoc, FPOptions FPFeatures,
SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
ADLCallKind UsesADL);
CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty);
@ -97,7 +102,7 @@ public:
static CXXOperatorCallExpr *
Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
SourceLocation OperatorLoc, FPOptions FPFeatures,
SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
ADLCallKind UsesADL = NotADL);
static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx,
@ -118,6 +123,22 @@ public:
}
bool isAssignmentOp() const { return isAssignmentOp(getOperator()); }
static bool isComparisonOp(OverloadedOperatorKind Opc) {
switch (Opc) {
case OO_EqualEqual:
case OO_ExclaimEqual:
case OO_Greater:
case OO_GreaterEqual:
case OO_Less:
case OO_LessEqual:
case OO_Spaceship:
return true;
default:
return false;
}
}
bool isComparisonOp() const { return isComparisonOp(getOperator()); }
/// Is this written as an infix binary operator?
bool isInfixBinaryOp() const;
@ -144,20 +165,10 @@ public:
return T->getStmtClass() == CXXOperatorCallExprClass;
}
// Set the FP contractability status of this operator. Only meaningful for
// Set the FPFeatures status of this operator. Only meaningful for
// operations on floating point types.
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 getFPFeatures().allowFPContractWithinStatement();
}
void setFPFeatures(FPOptionsOverride F) { Overrides = F; }
FPOptionsOverride getFPFeatures() const { return Overrides; }
};
/// Represents a call to a member function that
@ -279,12 +290,10 @@ class CXXRewrittenBinaryOperator : public Expr {
public:
CXXRewrittenBinaryOperator(Expr *SemanticForm, bool IsReversed)
: Expr(CXXRewrittenBinaryOperatorClass, SemanticForm->getType(),
SemanticForm->getValueKind(), SemanticForm->getObjectKind(),
SemanticForm->isTypeDependent(), SemanticForm->isValueDependent(),
SemanticForm->isInstantiationDependent(),
SemanticForm->containsUnexpandedParameterPack()),
SemanticForm->getValueKind(), SemanticForm->getObjectKind()),
SemanticForm(SemanticForm) {
CXXRewrittenBinaryOperatorBits.IsReversed = IsReversed;
setDependence(computeDependence(this));
}
CXXRewrittenBinaryOperator(EmptyShell Empty)
: Expr(CXXRewrittenBinaryOperatorClass, Empty), SemanticForm() {}
@ -349,7 +358,8 @@ public:
/// This abstract class is inherited by all of the classes
/// representing "named" casts: CXXStaticCastExpr for \c static_cast,
/// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for
/// reinterpret_cast, and CXXConstCastExpr for \c const_cast.
/// reinterpret_cast, CXXConstCastExpr for \c const_cast and
/// CXXAddrspaceCastExpr for addrspace_cast (in OpenCL).
class CXXNamedCastExpr : public ExplicitCastExpr {
private:
// the location of the casting op
@ -395,6 +405,7 @@ public:
case CXXDynamicCastExprClass:
case CXXReinterpretCastExprClass:
case CXXConstCastExprClass:
case CXXAddrspaceCastExprClass:
return true;
default:
return false;
@ -552,6 +563,41 @@ public:
}
};
/// A C++ addrspace_cast expression (currently only enabled for OpenCL).
///
/// This expression node represents a cast between pointers to objects in
/// different address spaces e.g.,
/// \c addrspace_cast<global int*>(PtrToGenericInt).
///
/// A addrspace_cast can cast address space type qualifiers but does not change
/// the underlying value.
class CXXAddrspaceCastExpr final
: public CXXNamedCastExpr,
private llvm::TrailingObjects<CXXAddrspaceCastExpr, CXXBaseSpecifier *> {
CXXAddrspaceCastExpr(QualType ty, ExprValueKind VK, CastKind Kind, Expr *op,
TypeSourceInfo *writtenTy, SourceLocation l,
SourceLocation RParenLoc, SourceRange AngleBrackets)
: CXXNamedCastExpr(CXXAddrspaceCastExprClass, ty, VK, Kind, op, 0,
writtenTy, l, RParenLoc, AngleBrackets) {}
explicit CXXAddrspaceCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXAddrspaceCastExprClass, Empty, 0) {}
public:
friend class CastExpr;
friend TrailingObjects;
static CXXAddrspaceCastExpr *
Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind,
Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L,
SourceLocation RParenLoc, SourceRange AngleBrackets);
static CXXAddrspaceCastExpr *CreateEmpty(const ASTContext &Context);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXAddrspaceCastExprClass;
}
};
/// A call to a literal operator (C++11 [over.literal])
/// written as a user-defined literal (C++11 [lit.ext]).
///
@ -645,10 +691,10 @@ public:
class CXXBoolLiteralExpr : public Expr {
public:
CXXBoolLiteralExpr(bool Val, QualType Ty, SourceLocation Loc)
: Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
false, false) {
: Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary) {
CXXBoolLiteralExprBits.Value = Val;
CXXBoolLiteralExprBits.Loc = Loc;
setDependence(ExprDependence::None);
}
explicit CXXBoolLiteralExpr(EmptyShell Empty)
@ -683,9 +729,9 @@ public:
class CXXNullPtrLiteralExpr : public Expr {
public:
CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc)
: Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false,
false, false, false) {
: Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary) {
CXXNullPtrLiteralExprBits.Loc = Loc;
setDependence(ExprDependence::None);
}
explicit CXXNullPtrLiteralExpr(EmptyShell Empty)
@ -723,11 +769,10 @@ public:
friend class ASTStmtReader;
CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr)
: Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary,
Ty->isDependentType(), SubExpr->isValueDependent(),
SubExpr->isInstantiationDependent(),
SubExpr->containsUnexpandedParameterPack()),
SubExpr(SubExpr) {}
: Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary),
SubExpr(SubExpr) {
setDependence(computeDependence(this));
}
Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); }
const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); }
@ -762,32 +807,24 @@ public:
///
/// This represents code like \c typeid(int) or \c typeid(*objPtr)
class CXXTypeidExpr : public Expr {
friend class ASTStmtReader;
private:
llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
SourceRange Range;
public:
CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
: Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
// typeid is never type-dependent (C++ [temp.dep.expr]p4)
false,
// typeid is value-dependent if the type or expression are
// dependent
Operand->getType()->isDependentType(),
Operand->getType()->isInstantiationDependentType(),
Operand->getType()->containsUnexpandedParameterPack()),
Operand(Operand), Range(R) {}
: Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand),
Range(R) {
setDependence(computeDependence(this));
}
CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R)
: Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary,
// typeid is never type-dependent (C++ [temp.dep.expr]p4)
false,
// typeid is value-dependent if the type or expression are
// dependent
Operand->isTypeDependent() || Operand->isValueDependent(),
Operand->isInstantiationDependent(),
Operand->containsUnexpandedParameterPack()),
Operand(Operand), Range(R) {}
: Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand),
Range(R) {
setDependence(computeDependence(this));
}
CXXTypeidExpr(EmptyShell Empty, bool isExpr)
: Expr(CXXTypeidExprClass, Empty) {
@ -812,22 +849,11 @@ public:
assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
return Operand.get<TypeSourceInfo *>();
}
void setTypeOperandSourceInfo(TypeSourceInfo *TSI) {
assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
Operand = TSI;
}
Expr *getExprOperand() const {
assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
return static_cast<Expr*>(Operand.get<Stmt *>());
}
void setExprOperand(Expr *E) {
assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
Operand = E;
}
SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
@ -872,15 +898,12 @@ public:
MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow,
QualType ty, ExprValueKind VK,
NestedNameSpecifierLoc qualifierLoc,
SourceLocation nameLoc)
: Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary,
/*type-dependent*/ false, baseExpr->isValueDependent(),
baseExpr->isInstantiationDependent(),
baseExpr->containsUnexpandedParameterPack()),
BaseExpr(baseExpr), TheDecl(decl),
MemberLoc(nameLoc), IsArrow(isArrow),
QualifierLoc(qualifierLoc) {}
NestedNameSpecifierLoc qualifierLoc, SourceLocation nameLoc)
: Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary), BaseExpr(baseExpr),
TheDecl(decl), MemberLoc(nameLoc), IsArrow(isArrow),
QualifierLoc(qualifierLoc) {
setDependence(computeDependence(this));
}
MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {}
@ -948,12 +971,11 @@ class MSPropertySubscriptExpr : public Expr {
public:
MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK,
ExprObjectKind OK, SourceLocation RBracketLoc)
: Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(),
Idx->isValueDependent(), Idx->isInstantiationDependent(),
Idx->containsUnexpandedParameterPack()),
: Expr(MSPropertySubscriptExprClass, Ty, VK, OK),
RBracketLoc(RBracketLoc) {
SubExprs[BASE_EXPR] = Base;
SubExprs[IDX_EXPR] = Idx;
setDependence(computeDependence(this));
}
/// Create an empty array subscript expression.
@ -998,25 +1020,26 @@ public:
///
/// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr)
class CXXUuidofExpr : public Expr {
friend class ASTStmtReader;
private:
llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
StringRef UuidStr;
MSGuidDecl *Guid;
SourceRange Range;
public:
CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, StringRef UuidStr,
CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, MSGuidDecl *Guid,
SourceRange R)
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false,
Operand->getType()->isDependentType(),
Operand->getType()->isInstantiationDependentType(),
Operand->getType()->containsUnexpandedParameterPack()),
Operand(Operand), UuidStr(UuidStr), Range(R) {}
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand),
Guid(Guid), Range(R) {
setDependence(computeDependence(this));
}
CXXUuidofExpr(QualType Ty, Expr *Operand, StringRef UuidStr, SourceRange R)
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false,
Operand->isTypeDependent(), Operand->isInstantiationDependent(),
Operand->containsUnexpandedParameterPack()),
Operand(Operand), UuidStr(UuidStr), Range(R) {}
CXXUuidofExpr(QualType Ty, Expr *Operand, MSGuidDecl *Guid, SourceRange R)
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand),
Guid(Guid), Range(R) {
setDependence(computeDependence(this));
}
CXXUuidofExpr(EmptyShell Empty, bool isExpr)
: Expr(CXXUuidofExprClass, Empty) {
@ -1037,24 +1060,12 @@ public:
assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
return Operand.get<TypeSourceInfo *>();
}
void setTypeOperandSourceInfo(TypeSourceInfo *TSI) {
assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
Operand = TSI;
}
Expr *getExprOperand() const {
assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)");
return static_cast<Expr*>(Operand.get<Stmt *>());
}
void setExprOperand(Expr *E) {
assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)");
Operand = E;
}
void setUuidStr(StringRef US) { UuidStr = US; }
StringRef getUuidStr() const { return UuidStr; }
MSGuidDecl *getGuidDecl() const { return Guid; }
SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
@ -1097,14 +1108,10 @@ public:
class CXXThisExpr : public Expr {
public:
CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit)
: Expr(CXXThisExprClass, Ty, VK_RValue, OK_Ordinary,
// 'this' is type-dependent if the class type of the enclosing
// member function is dependent (C++ [temp.dep.expr]p2)
Ty->isDependentType(), Ty->isDependentType(),
Ty->isInstantiationDependentType(),
/*ContainsUnexpandedParameterPack=*/false) {
: Expr(CXXThisExprClass, Ty, VK_RValue, OK_Ordinary) {
CXXThisExprBits.IsImplicit = IsImplicit;
CXXThisExprBits.Loc = L;
setDependence(computeDependence(this));
}
CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {}
@ -1150,12 +1157,10 @@ public:
// null if not present.
CXXThrowExpr(Expr *Operand, QualType Ty, SourceLocation Loc,
bool IsThrownVariableInScope)
: Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
Operand && Operand->isInstantiationDependent(),
Operand && Operand->containsUnexpandedParameterPack()),
Operand(Operand) {
: Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary), Operand(Operand) {
CXXThrowExprBits.ThrowLoc = Loc;
CXXThrowExprBits.IsThrownVariableInScope = IsThrownVariableInScope;
setDependence(computeDependence(this));
}
CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {}
@ -1209,16 +1214,16 @@ class CXXDefaultArgExpr final : public Expr {
DeclContext *UsedContext;
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param,
DeclContext *UsedContext)
DeclContext *UsedContext)
: Expr(SC,
Param->hasUnparsedDefaultArg()
? Param->getType().getNonReferenceType()
: Param->getDefaultArg()->getType(),
Param->getDefaultArg()->getValueKind(),
Param->getDefaultArg()->getObjectKind(), false, false, false,
false),
Param->getDefaultArg()->getObjectKind()),
Param(Param), UsedContext(UsedContext) {
CXXDefaultArgExprBits.Loc = Loc;
setDependence(ExprDependence::None);
}
public:
@ -1374,13 +1379,12 @@ class CXXBindTemporaryExpr : public Expr {
CXXTemporary *Temp = nullptr;
Stmt *SubExpr = nullptr;
CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr)
: Expr(CXXBindTemporaryExprClass, SubExpr->getType(),
VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(),
SubExpr->isValueDependent(),
SubExpr->isInstantiationDependent(),
SubExpr->containsUnexpandedParameterPack()),
Temp(temp), SubExpr(SubExpr) {}
CXXBindTemporaryExpr(CXXTemporary *temp, Expr *SubExpr)
: Expr(CXXBindTemporaryExprClass, SubExpr->getType(), VK_RValue,
OK_Ordinary),
Temp(temp), SubExpr(SubExpr) {
setDependence(computeDependence(this));
}
public:
CXXBindTemporaryExpr(EmptyShell Empty)
@ -1631,12 +1635,12 @@ public:
CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T,
CXXConstructorDecl *Ctor, bool ConstructsVirtualBase,
bool InheritedFromVirtualBase)
: Expr(CXXInheritedCtorInitExprClass, T, VK_RValue, OK_Ordinary, false,
false, false, false),
: Expr(CXXInheritedCtorInitExprClass, T, VK_RValue, OK_Ordinary),
Constructor(Ctor), Loc(Loc),
ConstructsVirtualBase(ConstructsVirtualBase),
InheritedFromVirtualBase(InheritedFromVirtualBase) {
assert(!T->isDependentType());
setDependence(ExprDependence::None);
}
/// Construct an empty C++ inheriting construction expression.
@ -1817,26 +1821,14 @@ Stmt **CXXConstructExpr::getTrailingArgs() {
/// and which can never occur implicitly.
class LambdaExpr final : public Expr,
private llvm::TrailingObjects<LambdaExpr, Stmt *> {
// LambdaExpr has some data stored in LambdaExprBits.
/// The source range that covers the lambda introducer ([...]).
SourceRange IntroducerRange;
/// The source location of this lambda's capture-default ('=' or '&').
SourceLocation CaptureDefaultLoc;
/// The number of captures.
unsigned NumCaptures : 16;
/// The default capture kind, which is a value of type
/// LambdaCaptureDefault.
unsigned CaptureDefault : 2;
/// Whether this lambda had an explicit parameter list vs. an
/// implicit (and empty) parameter list.
unsigned ExplicitParams : 1;
/// Whether this lambda had the result type explicitly specified.
unsigned ExplicitResultType : 1;
/// The location of the closing brace ('}') that completes
/// the lambda.
///
@ -1850,23 +1842,18 @@ class LambdaExpr final : public Expr,
/// Construct a lambda expression.
LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
bool ExplicitParams, bool ExplicitResultType,
ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack);
SourceLocation CaptureDefaultLoc, bool ExplicitParams,
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack);
/// Construct an empty lambda expression.
LambdaExpr(EmptyShell Empty, unsigned NumCaptures)
: Expr(LambdaExprClass, Empty), NumCaptures(NumCaptures),
CaptureDefault(LCD_None), ExplicitParams(false),
ExplicitResultType(false) {
getStoredStmts()[NumCaptures] = nullptr;
}
LambdaExpr(EmptyShell Empty, unsigned NumCaptures);
Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); }
Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }
void initBodyIfNeeded() const;
public:
friend class ASTStmtReader;
friend class ASTStmtWriter;
@ -1876,9 +1863,9 @@ public:
static LambdaExpr *
Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc,
ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack);
bool ExplicitParams, bool ExplicitResultType,
ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack);
/// Construct a new lambda expression that will be deserialized from
/// an external source.
@ -1887,13 +1874,11 @@ public:
/// Determine the default capture kind for this lambda.
LambdaCaptureDefault getCaptureDefault() const {
return static_cast<LambdaCaptureDefault>(CaptureDefault);
return static_cast<LambdaCaptureDefault>(LambdaExprBits.CaptureDefault);
}
/// Retrieve the location of this lambda's capture-default, if any.
SourceLocation getCaptureDefaultLoc() const {
return CaptureDefaultLoc;
}
SourceLocation getCaptureDefaultLoc() const { return CaptureDefaultLoc; }
/// Determine whether one of this lambda's captures is an init-capture.
bool isInitCapture(const LambdaCapture *Capture) const;
@ -1916,7 +1901,7 @@ public:
capture_iterator capture_end() const;
/// Determine the number of captures in this lambda.
unsigned capture_size() const { return NumCaptures; }
unsigned capture_size() const { return LambdaExprBits.NumCaptures; }
/// Retrieve this lambda's explicit captures.
capture_range explicit_captures() const;
@ -1946,6 +1931,7 @@ public:
/// Const iterator that walks over the capture initialization
/// arguments.
/// FIXME: This interface is prone to being used incorrectly.
using const_capture_init_iterator = Expr *const *;
/// Retrieve the initialization expressions for this lambda's captures.
@ -1973,13 +1959,13 @@ public:
/// Retrieve the iterator pointing one past the last
/// initialization argument for this lambda expression.
capture_init_iterator capture_init_end() {
return capture_init_begin() + NumCaptures;
return capture_init_begin() + capture_size();
}
/// Retrieve the iterator pointing one past the last
/// initialization argument for this lambda expression.
const_capture_init_iterator capture_init_end() const {
return capture_init_begin() + NumCaptures;
return capture_init_begin() + capture_size();
}
/// Retrieve the source range covering the lambda introducer,
@ -2013,8 +1999,20 @@ public:
/// Whether this is a generic lambda.
bool isGenericLambda() const { return getTemplateParameterList(); }
/// Retrieve the body of the lambda.
CompoundStmt *getBody() const;
/// Retrieve the body of the lambda. This will be most of the time
/// a \p CompoundStmt, but can also be \p CoroutineBodyStmt wrapping
/// a \p CompoundStmt. Note that unlike functions, lambda-expressions
/// cannot have a function-try-block.
Stmt *getBody() const;
/// Retrieve the \p CompoundStmt representing the body of the lambda.
/// This is a convenience function for callers who do not need
/// to handle node(s) which may wrap a \p CompoundStmt.
const CompoundStmt *getCompoundStmtBody() const;
CompoundStmt *getCompoundStmtBody() {
const auto *ConstThis = this;
return const_cast<CompoundStmt *>(ConstThis->getCompoundStmtBody());
}
/// Determine whether the lambda is mutable, meaning that any
/// captures values can be modified.
@ -2022,10 +2020,12 @@ public:
/// Determine whether this lambda has an explicit parameter
/// list vs. an implicit (empty) parameter list.
bool hasExplicitParameters() const { return ExplicitParams; }
bool hasExplicitParameters() const { return LambdaExprBits.ExplicitParams; }
/// Whether this lambda had its result type explicitly specified.
bool hasExplicitResultType() const { return ExplicitResultType; }
bool hasExplicitResultType() const {
return LambdaExprBits.ExplicitResultType;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == LambdaExprClass;
@ -2037,15 +2037,9 @@ public:
SourceLocation getEndLoc() const LLVM_READONLY { return ClosingBrace; }
child_range children() {
// Includes initialization exprs plus body stmt
return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1);
}
const_child_range children() const {
return const_child_range(getStoredStmts(),
getStoredStmts() + NumCaptures + 1);
}
/// Includes the captures and the body of the lambda.
child_range children();
const_child_range children() const;
};
/// An expression "T()" which creates a value-initialized rvalue of type
@ -2060,11 +2054,10 @@ public:
/// expression.
CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo,
SourceLocation RParenLoc)
: Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, false,
false, Type->isInstantiationDependentType(),
Type->containsUnexpandedParameterPack()),
: Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary),
TypeInfo(TypeInfo) {
CXXScalarValueInitExprBits.RParenLoc = RParenLoc;
setDependence(computeDependence(this));
}
explicit CXXScalarValueInitExpr(EmptyShell Shell)
@ -2369,15 +2362,14 @@ public:
CXXDeleteExpr(QualType Ty, bool GlobalDelete, bool ArrayForm,
bool ArrayFormAsWritten, bool UsualArrayDeleteWantsSize,
FunctionDecl *OperatorDelete, Expr *Arg, SourceLocation Loc)
: Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary, false,
Arg->isValueDependent(), Arg->isInstantiationDependent(),
Arg->containsUnexpandedParameterPack()),
: Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary),
OperatorDelete(OperatorDelete), Argument(Arg) {
CXXDeleteExprBits.GlobalDelete = GlobalDelete;
CXXDeleteExprBits.ArrayForm = ArrayForm;
CXXDeleteExprBits.ArrayFormAsWritten = ArrayFormAsWritten;
CXXDeleteExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize;
CXXDeleteExprBits.Loc = Loc;
setDependence(computeDependence(this));
}
explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell) {}
@ -2735,15 +2727,15 @@ public:
friend class ASTStmtReader;
ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att,
TypeSourceInfo *queried, uint64_t value,
Expr *dimension, SourceLocation rparen, QualType ty)
: Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary,
false, queried->getType()->isDependentType(),
(queried->getType()->isInstantiationDependentType() ||
(dimension && dimension->isInstantiationDependent())),
queried->getType()->containsUnexpandedParameterPack()),
ATT(att), Value(value), Dimension(dimension),
Loc(loc), RParen(rparen), QueriedType(queried) {}
TypeSourceInfo *queried, uint64_t value, Expr *dimension,
SourceLocation rparen, QualType ty)
: Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary), ATT(att),
Value(value), Dimension(dimension), Loc(loc), RParen(rparen),
QueriedType(queried) {
assert(att <= ATT_Last && "invalid enum value!");
assert(static_cast<unsigned>(att) == ATT && "ATT overflow!");
setDependence(computeDependence(this));
}
explicit ArrayTypeTraitExpr(EmptyShell Empty)
: Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {}
@ -2801,17 +2793,15 @@ class ExpressionTraitExpr : public Expr {
public:
friend class ASTStmtReader;
ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et,
Expr *queried, bool value,
SourceLocation rparen, QualType resultType)
: Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Not type-dependent
// Value-dependent if the argument is type-dependent.
queried->isTypeDependent(),
queried->isInstantiationDependent(),
queried->containsUnexpandedParameterPack()),
ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, Expr *queried,
bool value, SourceLocation rparen, QualType resultType)
: Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary),
ET(et), Value(value), Loc(loc), RParen(rparen),
QueriedExpression(queried) {}
QueriedExpression(queried) {
assert(et <= ET_Last && "invalid enum value!");
assert(static_cast<unsigned>(et) == ET && "ET overflow!");
setDependence(computeDependence(this));
}
explicit ExpressionTraitExpr(EmptyShell Empty)
: Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {}
@ -3305,13 +3295,15 @@ public:
/// literal is the extent of the enclosing scope.
class ExprWithCleanups final
: public FullExpr,
private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> {
private llvm::TrailingObjects<
ExprWithCleanups,
llvm::PointerUnion<BlockDecl *, CompoundLiteralExpr *>> {
public:
/// The type of objects that are kept in the cleanup.
/// It's useful to remember the set of blocks; we could also
/// remember the set of temporaries, but there's currently
/// no need.
using CleanupObject = BlockDecl *;
/// It's useful to remember the set of blocks and block-scoped compound
/// literals; we could also remember the set of temporaries, but there's
/// currently no need.
using CleanupObject = llvm::PointerUnion<BlockDecl *, CompoundLiteralExpr *>;
private:
friend class ASTStmtReader;
@ -3964,13 +3956,10 @@ class CXXNoexceptExpr : public Expr {
public:
CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val,
SourceLocation Keyword, SourceLocation RParen)
: Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary,
/*TypeDependent*/ false,
/*ValueDependent*/ Val == CT_Dependent,
Val == CT_Dependent || Operand->isInstantiationDependent(),
Operand->containsUnexpandedParameterPack()),
: Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary),
Operand(Operand), Range(Keyword, RParen) {
CXXNoexceptExprBits.Value = Val == CT_Cannot;
setDependence(computeDependence(this, Val));
}
CXXNoexceptExpr(EmptyShell Empty) : Expr(CXXNoexceptExprClass, Empty) {}
@ -4031,12 +4020,12 @@ public:
PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc,
Optional<unsigned> NumExpansions)
: Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
Pattern->getObjectKind(), /*TypeDependent=*/true,
/*ValueDependent=*/true, /*InstantiationDependent=*/true,
/*ContainsUnexpandedParameterPack=*/false),
Pattern->getObjectKind()),
EllipsisLoc(EllipsisLoc),
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0),
Pattern(Pattern) {}
Pattern(Pattern) {
setDependence(computeDependence(this));
}
PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {}
@ -4123,17 +4112,17 @@ class SizeOfPackExpr final
/// the given parameter pack.
SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
SourceLocation PackLoc, SourceLocation RParenLoc,
Optional<unsigned> Length, ArrayRef<TemplateArgument> PartialArgs)
: Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
/*TypeDependent=*/false, /*ValueDependent=*/!Length,
/*InstantiationDependent=*/!Length,
/*ContainsUnexpandedParameterPack=*/false),
Optional<unsigned> Length,
ArrayRef<TemplateArgument> PartialArgs)
: Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary),
OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
Length(Length ? *Length : PartialArgs.size()), Pack(Pack) {
assert((!Length || PartialArgs.empty()) &&
"have partial args for non-dependent sizeof... expression");
auto *Args = getTrailingObjects<TemplateArgument>();
std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args);
setDependence(Length ? ExprDependence::None
: ExprDependence::ValueInstantiation);
}
/// Create an empty expression.
@ -4224,12 +4213,10 @@ public:
SourceLocation Loc,
NonTypeTemplateParmDecl *Param,
Expr *Replacement)
: Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary,
Replacement->isTypeDependent(), Replacement->isValueDependent(),
Replacement->isInstantiationDependent(),
Replacement->containsUnexpandedParameterPack()),
: Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary),
Param(Param), Replacement(Replacement) {
SubstNonTypeTemplateParmExprBits.NameLoc = Loc;
setDependence(computeDependence(this));
}
SourceLocation getNameLoc() const {
@ -4543,13 +4530,12 @@ public:
CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS,
BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS,
SourceLocation RParenLoc, Optional<unsigned> NumExpansions)
: Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary,
/*Dependent*/ true, true, true,
/*ContainsUnexpandedParameterPack*/ false),
LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
: Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary), LParenLoc(LParenLoc),
EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) {
SubExprs[0] = LHS;
SubExprs[1] = RHS;
setDependence(computeDependence(this));
}
CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {}
@ -4624,27 +4610,25 @@ public:
Expr *Ready, Expr *Suspend, Expr *Resume,
OpaqueValueExpr *OpaqueValue)
: Expr(SC, Resume->getType(), Resume->getValueKind(),
Resume->getObjectKind(), Resume->isTypeDependent(),
Resume->isValueDependent(), Common->isInstantiationDependent(),
Common->containsUnexpandedParameterPack()),
Resume->getObjectKind()),
KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) {
SubExprs[SubExpr::Common] = Common;
SubExprs[SubExpr::Ready] = Ready;
SubExprs[SubExpr::Suspend] = Suspend;
SubExprs[SubExpr::Resume] = Resume;
setDependence(computeDependence(this));
}
CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty,
Expr *Common)
: Expr(SC, Ty, VK_RValue, OK_Ordinary, true, true, true,
Common->containsUnexpandedParameterPack()),
KeywordLoc(KeywordLoc) {
: Expr(SC, Ty, VK_RValue, OK_Ordinary), KeywordLoc(KeywordLoc) {
assert(Common->isTypeDependent() && Ty->isDependentType() &&
"wrong constructor for non-dependent co_await/co_yield expression");
SubExprs[SubExpr::Common] = Common;
SubExprs[SubExpr::Ready] = nullptr;
SubExprs[SubExpr::Suspend] = nullptr;
SubExprs[SubExpr::Resume] = nullptr;
setDependence(computeDependence(this));
}
CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
@ -4741,10 +4725,7 @@ class DependentCoawaitExpr : public Expr {
public:
DependentCoawaitExpr(SourceLocation KeywordLoc, QualType Ty, Expr *Op,
UnresolvedLookupExpr *OpCoawait)
: Expr(DependentCoawaitExprClass, Ty, VK_RValue, OK_Ordinary,
/*TypeDependent*/ true, /*ValueDependent*/ true,
/*InstantiationDependent*/ true,
Op->containsUnexpandedParameterPack()),
: Expr(DependentCoawaitExprClass, Ty, VK_RValue, OK_Ordinary),
KeywordLoc(KeywordLoc) {
// NOTE: A co_await expression is dependent on the coroutines promise
// type and may be dependent even when the `Op` expression is not.
@ -4752,6 +4733,7 @@ public:
"wrong constructor for non-dependent co_await/co_yield expression");
SubExprs[0] = Op;
SubExprs[1] = OpCoawait;
setDependence(computeDependence(this));
}
DependentCoawaitExpr(EmptyShell Empty)
@ -4826,6 +4808,8 @@ public:
: ExplicitCastExpr(BuiltinBitCastExprClass, T, VK, CK, SrcExpr, 0,
DstType),
KWLoc(KWLoc), RParenLoc(RParenLoc) {}
BuiltinBitCastExpr(EmptyShell Empty)
: ExplicitCastExpr(BuiltinBitCastExprClass, Empty, 0) {}
SourceLocation getBeginLoc() const LLVM_READONLY { return KWLoc; }
SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }

View file

@ -149,6 +149,7 @@ public:
enum RequirementKind { RK_Type, RK_Simple, RK_Compound, RK_Nested };
private:
const RequirementKind Kind;
// FIXME: use RequirementDependence to model dependence?
bool Dependent : 1;
bool ContainsUnexpandedParameterPack : 1;
bool Satisfied : 1;
@ -550,4 +551,4 @@ public:
} // namespace clang
#endif // LLVM_CLANG_AST_EXPRCONCEPTS_H
#endif // LLVM_CLANG_AST_EXPRCONCEPTS_H

View file

@ -13,8 +13,10 @@
#ifndef LLVM_CLANG_AST_EXPROBJC_H
#define LLVM_CLANG_AST_EXPROBJC_H
#include "clang/AST/ComputeDependence.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/SelectorLocationsKind.h"
@ -53,9 +55,10 @@ class ObjCStringLiteral : public Expr {
public:
ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
: Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
false, false),
String(SL), AtLoc(L) {}
: Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary), String(SL),
AtLoc(L) {
setDependence(ExprDependence::None);
}
explicit ObjCStringLiteral(EmptyShell Empty)
: Expr(ObjCStringLiteralClass, Empty) {}
@ -88,9 +91,10 @@ class ObjCBoolLiteralExpr : public Expr {
public:
ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l)
: Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
false, false),
Value(val), Loc(l) {}
: Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary), Value(val),
Loc(l) {
setDependence(ExprDependence::None);
}
explicit ObjCBoolLiteralExpr(EmptyShell Empty)
: Expr(ObjCBoolLiteralExprClass, Empty) {}
@ -129,13 +133,11 @@ class ObjCBoxedExpr : public Expr {
public:
friend class ASTStmtReader;
ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
SourceRange R)
: Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
E->isTypeDependent(), E->isValueDependent(),
E->isInstantiationDependent(),
E->containsUnexpandedParameterPack()),
SubExpr(E), BoxingMethod(method), Range(R) {}
ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method, SourceRange R)
: Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary), SubExpr(E),
BoxingMethod(method), Range(R) {
setDependence(computeDependence(this));
}
explicit ObjCBoxedExpr(EmptyShell Empty)
: Expr(ObjCBoxedExprClass, Empty) {}
@ -409,14 +411,12 @@ class ObjCEncodeExpr : public Expr {
SourceLocation AtLoc, RParenLoc;
public:
ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
SourceLocation at, SourceLocation rp)
: Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
EncodedType->getType()->isDependentType(),
EncodedType->getType()->isDependentType(),
EncodedType->getType()->isInstantiationDependentType(),
EncodedType->getType()->containsUnexpandedParameterPack()),
EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, SourceLocation at,
SourceLocation rp)
: Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary),
EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {
setDependence(computeDependence(this));
}
explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
@ -456,11 +456,12 @@ class ObjCSelectorExpr : public Expr {
SourceLocation AtLoc, RParenLoc;
public:
ObjCSelectorExpr(QualType T, Selector selInfo,
SourceLocation at, SourceLocation rp)
: Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
false, false),
SelName(selInfo), AtLoc(at), RParenLoc(rp) {}
ObjCSelectorExpr(QualType T, Selector selInfo, SourceLocation at,
SourceLocation rp)
: Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary),
SelName(selInfo), AtLoc(at), RParenLoc(rp) {
setDependence(ExprDependence::None);
}
explicit ObjCSelectorExpr(EmptyShell Empty)
: Expr(ObjCSelectorExprClass, Empty) {}
@ -508,11 +509,12 @@ public:
friend class ASTStmtReader;
friend class ASTStmtWriter;
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
SourceLocation at, SourceLocation protoLoc, SourceLocation rp)
: Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
false, false),
TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {}
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, SourceLocation at,
SourceLocation protoLoc, SourceLocation rp)
: Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary),
TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {
setDependence(ExprDependence::None);
}
explicit ObjCProtocolExpr(EmptyShell Empty)
: Expr(ObjCProtocolExprClass, Empty) {}
@ -558,17 +560,15 @@ class ObjCIvarRefExpr : public Expr {
bool IsFreeIvar : 1;
public:
ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
SourceLocation l, SourceLocation oploc,
Expr *base,
bool arrow = false, bool freeIvar = false)
ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l,
SourceLocation oploc, Expr *base, bool arrow = false,
bool freeIvar = false)
: Expr(ObjCIvarRefExprClass, t, VK_LValue,
d->isBitField() ? OK_BitField : OK_Ordinary,
/*TypeDependent=*/false, base->isValueDependent(),
base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
d->isBitField() ? OK_BitField : OK_Ordinary),
D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow),
IsFreeIvar(freeIvar) {}
IsFreeIvar(freeIvar) {
setDependence(computeDependence(this));
}
explicit ObjCIvarRefExpr(EmptyShell Empty)
: Expr(ObjCIvarRefExprClass, Empty) {}
@ -645,57 +645,53 @@ private:
llvm::PointerUnion<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver;
public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation l, Expr *base)
: Expr(ObjCPropertyRefExprClass, t, VK, OK,
/*TypeDependent=*/false, base->isValueDependent(),
base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
PropertyOrGetter(PD, false), IdLoc(l), Receiver(base) {
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK,
ExprObjectKind OK, SourceLocation l, Expr *base)
: Expr(ObjCPropertyRefExprClass, t, VK, OK), PropertyOrGetter(PD, false),
IdLoc(l), Receiver(base) {
assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
setDependence(computeDependence(this));
}
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation l, SourceLocation sl, QualType st)
: Expr(ObjCPropertyRefExprClass, t, VK, OK,
/*TypeDependent=*/false, false, st->isInstantiationDependentType(),
st->containsUnexpandedParameterPack()),
PropertyOrGetter(PD, false), IdLoc(l), ReceiverLoc(sl),
Receiver(st.getTypePtr()) {
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK,
ExprObjectKind OK, SourceLocation l, SourceLocation sl,
QualType st)
: Expr(ObjCPropertyRefExprClass, t, VK, OK), PropertyOrGetter(PD, false),
IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
setDependence(computeDependence(this));
}
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
QualType T, ExprValueKind VK, ExprObjectKind OK,
SourceLocation IdLoc, Expr *Base)
: Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
Base->isValueDependent(), Base->isInstantiationDependent(),
Base->containsUnexpandedParameterPack()),
: Expr(ObjCPropertyRefExprClass, T, VK, OK),
PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
IdLoc(IdLoc), Receiver(Base) {
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
setDependence(computeDependence(this));
}
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
QualType T, ExprValueKind VK, ExprObjectKind OK,
SourceLocation IdLoc,
SourceLocation SuperLoc, QualType SuperTy)
: Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
SourceLocation IdLoc, SourceLocation SuperLoc,
QualType SuperTy)
: Expr(ObjCPropertyRefExprClass, T, VK, OK),
PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
setDependence(computeDependence(this));
}
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
QualType T, ExprValueKind VK, ExprObjectKind OK,
SourceLocation IdLoc,
SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
: Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
SourceLocation IdLoc, SourceLocation ReceiverLoc,
ObjCInterfaceDecl *Receiver)
: Expr(ObjCPropertyRefExprClass, T, VK, OK),
PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
setDependence(computeDependence(this));
}
explicit ObjCPropertyRefExpr(EmptyShell Empty)
@ -859,20 +855,14 @@ class ObjCSubscriptRefExpr : public Expr {
ObjCMethodDecl *SetAtIndexMethodDecl;
public:
ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
ExprValueKind VK, ExprObjectKind OK,
ObjCMethodDecl *getMethod,
ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T, ExprValueKind VK,
ExprObjectKind OK, ObjCMethodDecl *getMethod,
ObjCMethodDecl *setMethod, SourceLocation RB)
: Expr(ObjCSubscriptRefExprClass, T, VK, OK,
base->isTypeDependent() || key->isTypeDependent(),
base->isValueDependent() || key->isValueDependent(),
(base->isInstantiationDependent() ||
key->isInstantiationDependent()),
(base->containsUnexpandedParameterPack() ||
key->containsUnexpandedParameterPack())),
RBracket(RB), GetAtIndexMethodDecl(getMethod),
SetAtIndexMethodDecl(setMethod) {
SubExprs[BASE] = base; SubExprs[KEY] = key;
: Expr(ObjCSubscriptRefExprClass, T, VK, OK), RBracket(RB),
GetAtIndexMethodDecl(getMethod), SetAtIndexMethodDecl(setMethod) {
SubExprs[BASE] = base;
SubExprs[KEY] = key;
setDependence(computeDependence(this));
}
explicit ObjCSubscriptRefExpr(EmptyShell Empty)
@ -1505,11 +1495,10 @@ class ObjCIsaExpr : public Expr {
public:
ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc,
QualType ty)
: Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
/*TypeDependent=*/false, base->isValueDependent(),
base->isInstantiationDependent(),
/*ContainsUnexpandedParameterPack=*/false),
Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {}
: Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary), Base(base),
IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {
setDependence(computeDependence(this));
}
/// Build an empty expression.
explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) {}
@ -1591,12 +1580,10 @@ class ObjCIndirectCopyRestoreExpr : public Expr {
public:
ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy)
: Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary,
operand->isTypeDependent(), operand->isValueDependent(),
operand->isInstantiationDependent(),
operand->containsUnexpandedParameterPack()),
: Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary),
Operand(operand) {
setShouldCopy(shouldCopy);
setDependence(computeDependence(this));
}
Expr *getSubExpr() { return cast<Expr>(Operand); }
@ -1705,9 +1692,10 @@ class ObjCAvailabilityCheckExpr : public Expr {
public:
ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc,
SourceLocation RParen, QualType Ty)
: Expr(ObjCAvailabilityCheckExprClass, Ty, VK_RValue, OK_Ordinary, false,
false, false, false),
VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) {}
: Expr(ObjCAvailabilityCheckExprClass, Ty, VK_RValue, OK_Ordinary),
VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) {
setDependence(ExprDependence::None);
}
explicit ObjCAvailabilityCheckExpr(EmptyShell Shell)
: Expr(ObjCAvailabilityCheckExprClass, Shell) {}

View file

@ -13,62 +13,66 @@
#ifndef LLVM_CLANG_AST_EXPROPENMP_H
#define LLVM_CLANG_AST_EXPROPENMP_H
#include "clang/AST/ComputeDependence.h"
#include "clang/AST/Expr.h"
namespace clang {
/// OpenMP 4.0 [2.4, Array Sections].
/// OpenMP 5.0 [2.1.5, Array Sections].
/// To specify an array section in an OpenMP construct, array subscript
/// expressions are extended with the following syntax:
/// \code
/// [ lower-bound : length : stride ]
/// [ lower-bound : length : ]
/// [ lower-bound : length ]
/// [ lower-bound : : stride ]
/// [ lower-bound : : ]
/// [ lower-bound : ]
/// [ : length : stride ]
/// [ : length : ]
/// [ : length ]
/// [ : : stride ]
/// [ : : ]
/// [ : ]
/// \endcode
/// The array section must be a subset of the original array.
/// Array sections are allowed on multidimensional arrays. Base language array
/// subscript expressions can be used to specify length-one dimensions of
/// multidimensional array sections.
/// The lower-bound and length are integral type expressions. When evaluated
/// Each of the lower-bound, length, and stride expressions if specified must be
/// an integral type expressions of the base language. When evaluated
/// they represent a set of integer values as follows:
/// \code
/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length -
/// 1 }
/// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... ,
/// lower-bound + ((length - 1) * stride) }
/// \endcode
/// The lower-bound and length must evaluate to non-negative integers.
/// The stride must evaluate to a positive integer.
/// When the size of the array dimension is not known, the length must be
/// specified explicitly.
/// When the length is absent, it defaults to the size of the array dimension
/// minus the lower-bound.
/// When the lower-bound is absent it defaults to 0.
/// When the stride is absent it defaults to 1.
/// When the length is absent it defaults to ⌈(size lower-bound)/stride⌉,
/// where size is the size of the array dimension. When the lower-bound is
/// absent it defaults to 0.
class OMPArraySectionExpr : public Expr {
enum { BASE, LOWER_BOUND, LENGTH, END_EXPR };
enum { BASE, LOWER_BOUND, LENGTH, STRIDE, END_EXPR };
Stmt *SubExprs[END_EXPR];
SourceLocation ColonLoc;
SourceLocation ColonLocFirst;
SourceLocation ColonLocSecond;
SourceLocation RBracketLoc;
public:
OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation ColonLoc, SourceLocation RBracketLoc)
: Expr(
OMPArraySectionExprClass, Type, VK, OK,
Base->isTypeDependent() ||
(LowerBound && LowerBound->isTypeDependent()) ||
(Length && Length->isTypeDependent()),
Base->isValueDependent() ||
(LowerBound && LowerBound->isValueDependent()) ||
(Length && Length->isValueDependent()),
Base->isInstantiationDependent() ||
(LowerBound && LowerBound->isInstantiationDependent()) ||
(Length && Length->isInstantiationDependent()),
Base->containsUnexpandedParameterPack() ||
(LowerBound && LowerBound->containsUnexpandedParameterPack()) ||
(Length && Length->containsUnexpandedParameterPack())),
ColonLoc(ColonLoc), RBracketLoc(RBracketLoc) {
OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride,
QualType Type, ExprValueKind VK, ExprObjectKind OK,
SourceLocation ColonLocFirst,
SourceLocation ColonLocSecond, SourceLocation RBracketLoc)
: Expr(OMPArraySectionExprClass, Type, VK, OK),
ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond),
RBracketLoc(RBracketLoc) {
SubExprs[BASE] = Base;
SubExprs[LOWER_BOUND] = LowerBound;
SubExprs[LENGTH] = Length;
SubExprs[STRIDE] = Stride;
setDependence(computeDependence(this));
}
/// Create an empty array section expression.
@ -100,13 +104,22 @@ public:
/// Set length of the array section.
void setLength(Expr *E) { SubExprs[LENGTH] = E; }
/// Get stride of array section.
Expr *getStride() { return cast_or_null<Expr>(SubExprs[STRIDE]); }
const Expr *getStride() const { return cast_or_null<Expr>(SubExprs[STRIDE]); }
/// Set length of the array section.
void setStride(Expr *E) { SubExprs[STRIDE] = E; }
SourceLocation getBeginLoc() const LLVM_READONLY {
return getBase()->getBeginLoc();
}
SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
SourceLocation getColonLoc() const { return ColonLoc; }
void setColonLoc(SourceLocation L) { ColonLoc = L; }
SourceLocation getColonLocFirst() const { return ColonLocFirst; }
void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }
SourceLocation getColonLocSecond() const { return ColonLocSecond; }
void setColonLocSecond(SourceLocation L) { ColonLocSecond = L; }
SourceLocation getRBracketLoc() const { return RBracketLoc; }
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
@ -127,6 +140,286 @@ public:
return const_child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
}
};
/// An explicit cast in C or a C-style cast in C++, which uses the syntax
/// ([s1][s2]...[sn])expr. For example: @c ([3][3])f.
class OMPArrayShapingExpr final
: public Expr,
private llvm::TrailingObjects<OMPArrayShapingExpr, Expr *, SourceRange> {
friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
/// Base node.
SourceLocation LPLoc; /// The location of the left paren
SourceLocation RPLoc; /// The location of the right paren
unsigned NumDims = 0; /// Number of dimensions in the shaping expression.
/// Construct full expression.
OMPArrayShapingExpr(QualType ExprTy, Expr *Op, SourceLocation L,
SourceLocation R, ArrayRef<Expr *> Dims);
/// Construct an empty expression.
explicit OMPArrayShapingExpr(EmptyShell Shell, unsigned NumDims)
: Expr(OMPArrayShapingExprClass, Shell), NumDims(NumDims) {}
/// Sets the dimensions for the array shaping.
void setDimensions(ArrayRef<Expr *> Dims);
/// Sets the base expression for array shaping operation.
void setBase(Expr *Op) { getTrailingObjects<Expr *>()[NumDims] = Op; }
/// Sets source ranges for the brackets in the array shaping operation.
void setBracketsRanges(ArrayRef<SourceRange> BR);
unsigned numTrailingObjects(OverloadToken<Expr *>) const {
// Add an extra one for the base expression.
return NumDims + 1;
}
unsigned numTrailingObjects(OverloadToken<SourceRange>) const {
return NumDims;
}
public:
static OMPArrayShapingExpr *Create(const ASTContext &Context, QualType T,
Expr *Op, SourceLocation L,
SourceLocation R, ArrayRef<Expr *> Dims,
ArrayRef<SourceRange> BracketRanges);
static OMPArrayShapingExpr *CreateEmpty(const ASTContext &Context,
unsigned NumDims);
SourceLocation getLParenLoc() const { return LPLoc; }
void setLParenLoc(SourceLocation L) { LPLoc = L; }
SourceLocation getRParenLoc() const { return RPLoc; }
void setRParenLoc(SourceLocation L) { RPLoc = L; }
SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; }
SourceLocation getEndLoc() const LLVM_READONLY {
return getBase()->getEndLoc();
}
/// Fetches the dimensions for array shaping expression.
ArrayRef<Expr *> getDimensions() const {
return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumDims);
}
/// Fetches source ranges for the brackets os the array shaping expression.
ArrayRef<SourceRange> getBracketsRanges() const {
return llvm::makeArrayRef(getTrailingObjects<SourceRange>(), NumDims);
}
/// Fetches base expression of array shaping expression.
Expr *getBase() { return getTrailingObjects<Expr *>()[NumDims]; }
const Expr *getBase() const { return getTrailingObjects<Expr *>()[NumDims]; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPArrayShapingExprClass;
}
// Iterators
child_range children() {
Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
return child_range(Begin, Begin + NumDims + 1);
}
const_child_range children() const {
Stmt *const *Begin =
reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
return const_child_range(Begin, Begin + NumDims + 1);
}
};
/// Helper expressions and declaration for OMPIteratorExpr class for each
/// iteration space.
struct OMPIteratorHelperData {
/// Internal normalized counter.
VarDecl *CounterVD = nullptr;
/// Normalized upper bound. Normalized loop iterates from 0 to Upper with
/// step 1.
Expr *Upper = nullptr;
/// Update expression for the originally specified iteration variable,
/// calculated as VD = Begin + CounterVD * Step;
Expr *Update = nullptr;
/// Updater for the internal counter: ++CounterVD;
Expr *CounterUpdate = nullptr;
};
/// OpenMP 5.0 [2.1.6 Iterators]
/// Iterators are identifiers that expand to multiple values in the clause on
/// which they appear.
/// The syntax of the iterator modifier is as follows:
/// \code
/// iterator(iterators-definition)
/// \endcode
/// where iterators-definition is one of the following:
/// \code
/// iterator-specifier [, iterators-definition ]
/// \endcode
/// where iterator-specifier is one of the following:
/// \code
/// [ iterator-type ] identifier = range-specification
/// \endcode
/// where identifier is a base language identifier.
/// iterator-type is a type name.
/// range-specification is of the form begin:end[:step], where begin and end are
/// expressions for which their types can be converted to iterator-type and step
/// is an integral expression.
/// In an iterator-specifier, if the iterator-type is not specified then the
/// type of that iterator is of int type.
/// The iterator-type must be an integral or pointer type.
/// The iterator-type must not be const qualified.
class OMPIteratorExpr final
: public Expr,
private llvm::TrailingObjects<OMPIteratorExpr, Decl *, Expr *,
SourceLocation, OMPIteratorHelperData> {
public:
/// Iterator range representation begin:end[:step].
struct IteratorRange {
Expr *Begin = nullptr;
Expr *End = nullptr;
Expr *Step = nullptr;
};
/// Iterator definition representation.
struct IteratorDefinition {
Decl *IteratorDecl = nullptr;
IteratorRange Range;
SourceLocation AssignmentLoc;
SourceLocation ColonLoc, SecondColonLoc;
};
private:
friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
/// Offset in the list of expressions for subelements of the ranges.
enum class RangeExprOffset {
Begin = 0,
End = 1,
Step = 2,
Total = 3,
};
/// Offset in the list of locations for subelements of colon symbols
/// locations.
enum class RangeLocOffset {
AssignLoc = 0,
FirstColonLoc = 1,
SecondColonLoc = 2,
Total = 3,
};
/// Location of 'iterator' keyword.
SourceLocation IteratorKwLoc;
/// Location of '('.
SourceLocation LPLoc;
/// Location of ')'.
SourceLocation RPLoc;
/// Number of iterator definitions.
unsigned NumIterators = 0;
OMPIteratorExpr(QualType ExprTy, SourceLocation IteratorKwLoc,
SourceLocation L, SourceLocation R,
ArrayRef<IteratorDefinition> Data,
ArrayRef<OMPIteratorHelperData> Helpers);
/// Construct an empty expression.
explicit OMPIteratorExpr(EmptyShell Shell, unsigned NumIterators)
: Expr(OMPIteratorExprClass, Shell), NumIterators(NumIterators) {}
/// Sets basic declaration for the specified iterator definition.
void setIteratorDeclaration(unsigned I, Decl *D);
/// Sets the location of the assignment symbol for the specified iterator
/// definition.
void setAssignmentLoc(unsigned I, SourceLocation Loc);
/// Sets begin, end and optional step expressions for specified iterator
/// definition.
void setIteratorRange(unsigned I, Expr *Begin, SourceLocation ColonLoc,
Expr *End, SourceLocation SecondColonLoc, Expr *Step);
/// Sets helpers for the specified iteration space.
void setHelper(unsigned I, const OMPIteratorHelperData &D);
unsigned numTrailingObjects(OverloadToken<Decl *>) const {
return NumIterators;
}
unsigned numTrailingObjects(OverloadToken<Expr *>) const {
return NumIterators * static_cast<int>(RangeExprOffset::Total);
}
unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
return NumIterators * static_cast<int>(RangeLocOffset::Total);
}
public:
static OMPIteratorExpr *Create(const ASTContext &Context, QualType T,
SourceLocation IteratorKwLoc, SourceLocation L,
SourceLocation R,
ArrayRef<IteratorDefinition> Data,
ArrayRef<OMPIteratorHelperData> Helpers);
static OMPIteratorExpr *CreateEmpty(const ASTContext &Context,
unsigned NumIterators);
SourceLocation getLParenLoc() const { return LPLoc; }
void setLParenLoc(SourceLocation L) { LPLoc = L; }
SourceLocation getRParenLoc() const { return RPLoc; }
void setRParenLoc(SourceLocation L) { RPLoc = L; }
SourceLocation getIteratorKwLoc() const { return IteratorKwLoc; }
void setIteratorKwLoc(SourceLocation L) { IteratorKwLoc = L; }
SourceLocation getBeginLoc() const LLVM_READONLY { return IteratorKwLoc; }
SourceLocation getEndLoc() const LLVM_READONLY { return RPLoc; }
/// Gets the iterator declaration for the given iterator.
Decl *getIteratorDecl(unsigned I);
const Decl *getIteratorDecl(unsigned I) const {
return const_cast<OMPIteratorExpr *>(this)->getIteratorDecl(I);
}
/// Gets the iterator range for the given iterator.
IteratorRange getIteratorRange(unsigned I);
const IteratorRange getIteratorRange(unsigned I) const {
return const_cast<OMPIteratorExpr *>(this)->getIteratorRange(I);
}
/// Gets the location of '=' for the given iterator definition.
SourceLocation getAssignLoc(unsigned I) const;
/// Gets the location of the first ':' in the range for the given iterator
/// definition.
SourceLocation getColonLoc(unsigned I) const;
/// Gets the location of the second ':' (if any) in the range for the given
/// iteratori definition.
SourceLocation getSecondColonLoc(unsigned I) const;
/// Returns number of iterator definitions.
unsigned numOfIterators() const { return NumIterators; }
/// Fetches helper data for the specified iteration space.
OMPIteratorHelperData &getHelper(unsigned I);
const OMPIteratorHelperData &getHelper(unsigned I) const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPIteratorExprClass;
}
// Iterators
child_range children() {
Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
return child_range(
Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total));
}
const_child_range children() const {
Stmt *const *Begin =
reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
return const_child_range(
Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total));
}
};
} // end namespace clang
#endif

View file

@ -17,7 +17,6 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclBase.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@ -39,6 +38,7 @@ namespace clang {
class ASTConsumer;
class ASTContext;
class ASTSourceDescriptor;
class CXXBaseSpecifier;
class CXXCtorInitializer;
class CXXRecordDecl;
@ -165,31 +165,6 @@ public:
/// object file.
virtual bool DeclIsFromPCHWithObjectFile(const Decl *D) { return false; }
/// Abstracts clang modules and precompiled header files and holds
/// everything needed to generate debug info for an imported module
/// or PCH.
class ASTSourceDescriptor {
StringRef PCHModuleName;
StringRef Path;
StringRef ASTFile;
ASTFileSignature Signature;
const Module *ClangModule = nullptr;
public:
ASTSourceDescriptor() = default;
ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
ASTFileSignature Signature)
: PCHModuleName(std::move(Name)), Path(std::move(Path)),
ASTFile(std::move(ASTFile)), Signature(Signature) {}
ASTSourceDescriptor(const Module &M);
std::string getModuleName() const;
StringRef getPath() const { return Path; }
StringRef getASTFile() const { return ASTFile; }
ASTFileSignature getSignature() const { return Signature; }
const Module *getModuleOrNull() const { return ClangModule; }
};
/// Return a descriptor for the corresponding module, if one exists.
virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
@ -504,9 +479,8 @@ struct PointerLikeTypeTraits<
static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); }
static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); }
enum {
NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1
};
static constexpr int NumLowBitsAvailable =
PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1;
};
} // namespace llvm

View file

@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_GLOBALDECL_H
#define LLVM_CLANG_AST_GLOBALDECL_H
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
@ -33,17 +34,31 @@ enum class DynamicInitKind : unsigned {
AtExit,
};
enum class KernelReferenceKind : unsigned {
Kernel = 0,
Stub = 1,
};
/// GlobalDecl - represents a global declaration. This can either be a
/// CXXConstructorDecl and the constructor type (Base, Complete).
/// a CXXDestructorDecl and the destructor type (Base, Complete) or
/// a CXXDestructorDecl and the destructor type (Base, Complete),
/// a FunctionDecl and the kernel reference type (Kernel, Stub), or
/// a VarDecl, a FunctionDecl or a BlockDecl.
///
/// When a new type of GlobalDecl is added, the following places should
/// be updated to convert a Decl* to a GlobalDecl:
/// PredefinedExpr::ComputeName() in lib/AST/Expr.cpp.
/// getParentOfLocalEntity() in lib/AST/ItaniumMangle.cpp
/// ASTNameGenerator::Implementation::writeFuncOrVarName in lib/AST/Mangle.cpp
///
class GlobalDecl {
llvm::PointerIntPair<const Decl *, 2> Value;
llvm::PointerIntPair<const Decl *, 3> Value;
unsigned MultiVersionIndex = 0;
void Init(const Decl *D) {
assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
assert(!D->hasAttr<CUDAGlobalAttr>() && "Use other ctor with GPU kernels!");
Value.setPointer(D);
}
@ -53,8 +68,17 @@ public:
GlobalDecl(const VarDecl *D) { Init(D);}
GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0)
: MultiVersionIndex(MVIndex) {
Init(D);
if (!D->hasAttr<CUDAGlobalAttr>()) {
Init(D);
return;
}
Value.setPointerAndInt(D, unsigned(getDefaultKernelReference(D)));
}
GlobalDecl(const FunctionDecl *D, KernelReferenceKind Kind)
: Value(D, unsigned(Kind)) {
assert(D->hasAttr<CUDAGlobalAttr>() && "Decl is not a GPU kernel!");
}
GlobalDecl(const NamedDecl *D) { Init(D); }
GlobalDecl(const BlockDecl *D) { Init(D); }
GlobalDecl(const CapturedDecl *D) { Init(D); }
GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
@ -94,13 +118,22 @@ public:
}
unsigned getMultiVersionIndex() const {
assert(isa<FunctionDecl>(getDecl()) &&
assert(isa<FunctionDecl>(
getDecl()) &&
!cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
!isa<CXXConstructorDecl>(getDecl()) &&
!isa<CXXDestructorDecl>(getDecl()) &&
"Decl is not a plain FunctionDecl!");
return MultiVersionIndex;
}
KernelReferenceKind getKernelReferenceKind() const {
assert(isa<FunctionDecl>(getDecl()) &&
cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
"Decl is not a GPU kernel!");
return static_cast<KernelReferenceKind>(Value.getInt());
}
friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
return LHS.Value == RHS.Value &&
LHS.MultiVersionIndex == RHS.MultiVersionIndex;
@ -108,12 +141,19 @@ public:
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
explicit operator bool() const { return getAsOpaquePtr(); }
static GlobalDecl getFromOpaquePtr(void *P) {
GlobalDecl GD;
GD.Value.setFromOpaqueValue(P);
return GD;
}
static KernelReferenceKind getDefaultKernelReference(const FunctionDecl *D) {
return D->getLangOpts().CUDAIsDevice ? KernelReferenceKind::Kernel
: KernelReferenceKind::Stub;
}
GlobalDecl getWithDecl(const Decl *D) {
GlobalDecl Result(*this);
Result.Value.setPointer(D);
@ -136,6 +176,7 @@ public:
GlobalDecl getWithMultiVersionIndex(unsigned Index) {
assert(isa<FunctionDecl>(getDecl()) &&
!cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
!isa<CXXConstructorDecl>(getDecl()) &&
!isa<CXXDestructorDecl>(getDecl()) &&
"Decl is not a plain FunctionDecl!");
@ -143,6 +184,15 @@ public:
Result.MultiVersionIndex = Index;
return Result;
}
GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind) {
assert(isa<FunctionDecl>(getDecl()) &&
cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() &&
"Decl is not a GPU kernel!");
GlobalDecl Result(*this);
Result.Value.setInt(unsigned(Kind));
return Result;
}
};
} // namespace clang

View file

@ -23,10 +23,13 @@
#include "clang/AST/CommentVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/Type.h"
#include "llvm/Support/JSON.h"
namespace clang {
class APValue;
class NodeStreamer {
bool FirstChild = true;
bool TopLevel = true;
@ -64,7 +67,7 @@ public:
// We need to capture an owning-string in the lambda because the lambda
// is invoked in a deferred manner.
std::string LabelStr = !Label.empty() ? Label : "inner";
std::string LabelStr(!Label.empty() ? Label : "inner");
bool WasFirstChild = FirstChild;
auto DumpWithIndent = [=](bool IsLastChild) {
if (WasFirstChild) {
@ -201,6 +204,7 @@ public:
void Visit(const OMPClause *C);
void Visit(const BlockDecl::Capture &C);
void Visit(const GenericSelectionExpr::ConstAssociation &A);
void Visit(const APValue &Value, QualType Ty);
void VisitTypedefType(const TypedefType *TT);
void VisitFunctionType(const FunctionType *T);

View file

@ -35,10 +35,7 @@ class LocInfoType : public Type {
TypeSourceInfo *DeclInfo;
LocInfoType(QualType ty, TypeSourceInfo *TInfo)
: Type((TypeClass)LocInfo, ty, ty->isDependentType(),
ty->isInstantiationDependentType(), ty->isVariablyModifiedType(),
ty->containsUnexpandedParameterPack()),
DeclInfo(TInfo) {
: Type((TypeClass)LocInfo, ty, ty->getDependence()), DeclInfo(TInfo) {
assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?");
}
friend class Sema;

View file

@ -14,6 +14,7 @@
#define LLVM_CLANG_AST_MANGLE_H
#include "clang/AST/Decl.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/DenseMap.h"
@ -96,8 +97,8 @@ public:
virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0;
// FIXME: consider replacing raw_ostream & with something like SmallString &.
void mangleName(const NamedDecl *D, raw_ostream &);
virtual void mangleCXXName(const NamedDecl *D, raw_ostream &) = 0;
void mangleName(GlobalDecl GD, raw_ostream &);
virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0;
virtual void mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
raw_ostream &) = 0;
@ -109,11 +110,8 @@ public:
raw_ostream &) = 0;
virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
raw_ostream &) = 0;
virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
raw_ostream &) = 0;
virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&);
void mangleGlobalBlock(const BlockDecl *BD,
const NamedDecl *ID,
@ -151,9 +149,14 @@ public:
};
class ItaniumMangleContext : public MangleContext {
bool IsUniqueNameMangler = false;
public:
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
: MangleContext(C, D, MK_Itanium) {}
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D,
bool IsUniqueNameMangler)
: MangleContext(C, D, MK_Itanium),
IsUniqueNameMangler(IsUniqueNameMangler) {}
virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
@ -172,12 +175,17 @@ public:
virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;
virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0;
bool isUniqueNameMangler() { return IsUniqueNameMangler; }
static bool classof(const MangleContext *C) {
return C->getKind() == MK_Itanium;
}
static ItaniumMangleContext *create(ASTContext &Context,
DiagnosticsEngine &Diags);
DiagnosticsEngine &Diags,
bool IsUniqueNameMangler = false);
};
class MicrosoftMangleContext : public MangleContext {

View file

@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#include "clang/AST/DependenceFlags.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/FoldingSet.h"
@ -199,6 +200,8 @@ public:
return nullptr;
}
NestedNameSpecifierDependence getDependence() const;
/// Whether this nested name specifier refers to a dependent
/// type or not.
bool isDependent() const;
@ -211,6 +214,9 @@ public:
/// parameter pack (for C++11 variadic templates).
bool containsUnexpandedParameterPack() const;
/// Whether this nested name specifier contains an error.
bool containsErrors() const;
/// Print this nested name specifier to the given output stream. If
/// `ResolveTemplateArguments` is true, we'll print actual types, e.g.
/// `ns::SomeTemplate<int, MyClass>` instead of

View file

@ -1,4 +1,4 @@
//===-- NonTrivialTypeVisitor.h - Visitor for non-trivial Types *- C++ --*-===//
//===-- NonTrivialTypeVisitor.h - Visitor for non-trivial Types -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.

View file

@ -89,7 +89,7 @@ public:
// Save booleans until the end to lower the size of data to process.
void AddBoolean(bool value);
static bool isWhitelistedDecl(const Decl* D, const DeclContext *Parent);
static bool isDeclToBeProcessed(const Decl* D, const DeclContext *Parent);
private:
void AddDeclarationNameImpl(DeclarationName Name);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,144 @@
//===- ParentMapContext.h - Map of parents using DynTypedNode -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Similar to ParentMap.h, but generalizes to non-Stmt nodes, which can have
// multiple parents.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_PARENTMAPCONTEXT_H
#define LLVM_CLANG_AST_PARENTMAPCONTEXT_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"
namespace clang {
class DynTypedNodeList;
class ParentMapContext {
public:
ParentMapContext(ASTContext &Ctx);
~ParentMapContext();
/// Returns the parents of the given node (within the traversal scope).
///
/// Note that this will lazily compute the parents of all nodes
/// and store them for later retrieval. Thus, the first call is O(n)
/// in the number of AST nodes.
///
/// Caveats and FIXMEs:
/// Calculating the parent map over all AST nodes will need to load the
/// full AST. This can be undesirable in the case where the full AST is
/// expensive to create (for example, when using precompiled header
/// preambles). Thus, there are good opportunities for optimization here.
/// One idea is to walk the given node downwards, looking for references
/// to declaration contexts - once a declaration context is found, compute
/// the parent map for the declaration context; if that can satisfy the
/// request, loading the whole AST can be avoided. Note that this is made
/// more complex by statements in templates having multiple parents - those
/// problems can be solved by building closure over the templated parts of
/// the AST, which also avoids touching large parts of the AST.
/// Additionally, we will want to add an interface to already give a hint
/// where to search for the parents, for example when looking at a statement
/// inside a certain function.
///
/// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
/// NestedNameSpecifier or NestedNameSpecifierLoc.
template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node);
DynTypedNodeList getParents(const DynTypedNode &Node);
/// Clear parent maps.
void clear();
TraversalKind getTraversalKind() const { return Traversal; }
void setTraversalKind(TraversalKind TK) { Traversal = TK; }
const Expr *traverseIgnored(const Expr *E) const;
Expr *traverseIgnored(Expr *E) const;
DynTypedNode traverseIgnored(const DynTypedNode &N) const;
private:
ASTContext &ASTCtx;
class ParentMap;
TraversalKind Traversal = TK_AsIs;
std::unique_ptr<ParentMap> Parents;
};
class TraversalKindScope {
ParentMapContext &Ctx;
TraversalKind TK = TK_AsIs;
public:
TraversalKindScope(ASTContext &ASTCtx, llvm::Optional<TraversalKind> ScopeTK)
: Ctx(ASTCtx.getParentMapContext()) {
TK = Ctx.getTraversalKind();
if (ScopeTK)
Ctx.setTraversalKind(*ScopeTK);
}
~TraversalKindScope() { Ctx.setTraversalKind(TK); }
};
/// Container for either a single DynTypedNode or for an ArrayRef to
/// DynTypedNode. For use with ParentMap.
class DynTypedNodeList {
llvm::AlignedCharArrayUnion<DynTypedNode, ArrayRef<DynTypedNode>> Storage;
bool IsSingleNode;
public:
DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
new (Storage.buffer) DynTypedNode(N);
}
DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
new (Storage.buffer) ArrayRef<DynTypedNode>(A);
}
const DynTypedNode *begin() const {
if (!IsSingleNode)
return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
->begin();
return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
}
const DynTypedNode *end() const {
if (!IsSingleNode)
return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
->end();
return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1;
}
size_t size() const { return end() - begin(); }
bool empty() const { return begin() == end(); }
const DynTypedNode &operator[](size_t N) const {
assert(N < size() && "Out of bounds!");
return *(begin() + N);
}
};
template <typename NodeT>
inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) {
return getParents(DynTypedNode::create(Node));
}
template <typename NodeT>
inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) {
return getParentMapContext().getParents(Node);
}
template <>
inline DynTypedNodeList ASTContext::getParents(const DynTypedNode &Node) {
return getParentMapContext().getParents(Node);
}
} // namespace clang
#endif

View file

@ -36,7 +36,9 @@ protected:
public:
/// Remap a path to a form suitable for printing.
virtual std::string remapPath(StringRef Path) const { return Path; }
virtual std::string remapPath(StringRef Path) const {
return std::string(Path);
}
};
/// Describes how types, statements, expressions, and declarations should be
@ -55,12 +57,13 @@ struct PrintingPolicy {
SuppressLifetimeQualifiers(false),
SuppressTemplateArgsInCXXConstructors(false), Bool(LO.Bool),
Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11),
UseVoidForZeroParams(!LO.CPlusPlus), TerseOutput(false),
UseVoidForZeroParams(!LO.CPlusPlus),
SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false),
PolishForDeclaration(false), Half(LO.Half),
MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
MSVCFormatting(false), ConstantsAsWritten(false),
SuppressImplicitBase(false), FullyQualifiedName(false),
PrintCanonicalTypes(false) {}
PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true) {}
/// 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
@ -181,6 +184,10 @@ struct PrintingPolicy {
/// with zero parameters.
unsigned UseVoidForZeroParams : 1;
/// Whether nested templates must be closed like 'a\<b\<c\> \>' rather than
/// 'a\<b\<c\>\>'.
unsigned SplitTemplateClosers : 1;
/// Provide a 'terse' output.
///
/// For example, in this mode we don't print function bodies, class members,
@ -237,6 +244,11 @@ struct PrintingPolicy {
/// Whether to print types as written or canonically.
unsigned PrintCanonicalTypes : 1;
/// Whether to print an InjectedClassNameType with template arguments or as
/// written. When a template argument is unnamed, printing it results in
/// invalid C++ code.
unsigned PrintInjectedClassNameWithArguments : 1;
/// Callbacks to use to allow the behavior of printing to be customized.
const PrintingCallbacks *Callbacks = nullptr;
};

View file

@ -11,9 +11,9 @@
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Allocator.h"
#include <map>
namespace clang {
@ -21,7 +21,9 @@ namespace clang {
class ASTContext;
class ASTReader;
class Decl;
class DiagnosticsEngine;
class Preprocessor;
class SourceManager;
namespace comments {
class FullComment;
@ -173,23 +175,6 @@ private:
friend class ASTReader;
};
/// Compare comments' source locations.
template<>
class BeforeThanCompare<RawComment> {
const SourceManager &SM;
public:
explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { }
bool operator()(const RawComment &LHS, const RawComment &RHS) {
return SM.isBeforeInTranslationUnit(LHS.getBeginLoc(), RHS.getBeginLoc());
}
bool operator()(const RawComment *LHS, const RawComment *RHS) {
return operator()(*LHS, *RHS);
}
};
/// This class represents all comments included in the translation unit,
/// sorted in order of appearance in the translation unit.
class RawCommentList {

View file

@ -48,29 +48,6 @@
#include <cstddef>
#include <type_traits>
// The following three macros are used for meta programming. The code
// using them is responsible for defining macro OPERATOR().
// All unary operators.
#define UNARYOP_LIST() \
OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \
OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \
OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \
OPERATOR(Extension) OPERATOR(Coawait)
// All binary operators (excluding compound assign operators).
#define BINOP_LIST() \
OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \
OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \
OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \
OPERATOR(NE) OPERATOR(Cmp) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \
OPERATOR(LAnd) OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma)
// All compound assign operators.
#define CAO_LIST() \
OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \
OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor)
namespace clang {
// A helper macro to implement short-circuiting when recursing. It
@ -83,6 +60,42 @@ namespace clang {
return false; \
} while (false)
namespace detail {
template <typename T, typename U>
struct has_same_member_pointer_type : std::false_type {};
template <typename T, typename U, typename R, typename... P>
struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)>
: std::true_type {};
template <bool has_same_type> struct is_same_method_impl {
template <typename FirstMethodPtrTy, typename SecondMethodPtrTy>
static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
SecondMethodPtrTy SecondMethodPtr) {
return false;
}
};
template <> struct is_same_method_impl<true> {
template <typename FirstMethodPtrTy, typename SecondMethodPtrTy>
static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
SecondMethodPtrTy SecondMethodPtr) {
return FirstMethodPtr == SecondMethodPtr;
}
};
/// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr
/// are pointers to the same non-static member function.
template <typename FirstMethodPtrTy, typename SecondMethodPtrTy>
bool isSameMethod(FirstMethodPtrTy FirstMethodPtr,
SecondMethodPtrTy SecondMethodPtr) {
return is_same_method_impl<has_same_member_pointer_type<
FirstMethodPtrTy,
SecondMethodPtrTy>::value>::isSameMethod(FirstMethodPtr, SecondMethodPtr);
}
} // end namespace detail
/// A class that does preorder or postorder
/// depth-first traversal on the entire Clang AST and visits each node.
///
@ -325,26 +338,20 @@ public:
Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); }
private:
template<typename T, typename U>
struct has_same_member_pointer_type : std::false_type {};
template<typename T, typename U, typename R, typename... P>
struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)>
: std::true_type {};
// Traverse the given statement. If the most-derived traverse function takes a
// data recursion queue, pass it on; otherwise, discard it. Note that the
// first branch of this conditional must compile whether or not the derived
// class can take a queue, so if we're taking the second arm, make the first
// arm call our function rather than the derived class version.
#define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \
(has_same_member_pointer_type<decltype( \
&RecursiveASTVisitor::Traverse##NAME), \
decltype(&Derived::Traverse##NAME)>::value \
? static_cast<typename std::conditional< \
has_same_member_pointer_type< \
(::clang::detail::has_same_member_pointer_type< \
decltype(&RecursiveASTVisitor::Traverse##NAME), \
decltype(&Derived::Traverse##NAME)>::value \
? static_cast<std::conditional_t< \
::clang::detail::has_same_member_pointer_type< \
decltype(&RecursiveASTVisitor::Traverse##NAME), \
decltype(&Derived::Traverse##NAME)>::value, \
Derived &, RecursiveASTVisitor &>::type>(*this) \
Derived &, RecursiveASTVisitor &>>(*this) \
.Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \
: getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)))
@ -377,60 +384,6 @@ public:
bool Visit##CLASS(CLASS *S) { return true; }
#include "clang/AST/StmtNodes.inc"
// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
// operator methods. Unary operators are not classes in themselves
// (they're all opcodes in UnaryOperator) but do have visitors.
#define OPERATOR(NAME) \
bool TraverseUnary##NAME(UnaryOperator *S, \
DataRecursionQueue *Queue = nullptr) { \
if (!getDerived().shouldTraversePostOrder()) \
TRY_TO(WalkUpFromUnary##NAME(S)); \
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \
return true; \
} \
bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
TRY_TO(WalkUpFromUnaryOperator(S)); \
TRY_TO(VisitUnary##NAME(S)); \
return true; \
} \
bool VisitUnary##NAME(UnaryOperator *S) { return true; }
UNARYOP_LIST()
#undef OPERATOR
// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary
// operator methods. Binary operators are not classes in themselves
// (they're all opcodes in BinaryOperator) but do have visitors.
#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \
if (!getDerived().shouldTraversePostOrder()) \
TRY_TO(WalkUpFromBin##NAME(S)); \
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \
return true; \
} \
bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \
TRY_TO(VisitBin##NAME(S)); \
return true; \
} \
bool VisitBin##NAME(BINOP_TYPE *S) { return true; }
#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator)
BINOP_LIST()
#undef OPERATOR
// Define Traverse*(), WalkUpFrom*(), and Visit*() for compound
// assignment methods. Compound assignment operators are not
// classes in themselves (they're all opcodes in
// CompoundAssignOperator) but do have visitors.
#define OPERATOR(NAME) \
GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator)
CAO_LIST()
#undef OPERATOR
#undef GENERAL_BINOP_FALLBACK
// ---- Methods on Types ----
// FIXME: revamp to take TypeLoc's rather than Types.
@ -534,8 +487,8 @@ private:
bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
bool TraverseOMPLoopDirective(OMPLoopDirective *S);
bool TraverseOMPClause(OMPClause *C);
#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
#include "clang/Basic/OpenMPKinds.def"
#define OMP_CLAUSE_CLASS(Enum, Str, Class) bool Visit##Class(Class *C);
#include "llvm/Frontend/OpenMP/OMPKinds.def"
/// Process clauses with list of variables.
template <typename T> bool VisitOMPClauseList(T *Node);
/// Process clauses with pre-initis.
@ -549,42 +502,6 @@ private:
template <typename Derived>
bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
DataRecursionQueue *Queue) {
#define DISPATCH_STMT(NAME, CLASS, VAR) \
return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue);
// If we have a binary expr, dispatch to the subcode of the binop. A smart
// optimizer (e.g. LLVM) will fold this comparison into the switch stmt
// below.
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \
case BO_##NAME: \
DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
BINOP_LIST()
#undef OPERATOR
#undef BINOP_LIST
#define OPERATOR(NAME) \
case BO_##NAME##Assign: \
DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
CAO_LIST()
#undef OPERATOR
#undef CAO_LIST
}
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
#define OPERATOR(NAME) \
case UO_##NAME: \
DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
UNARYOP_LIST()
#undef OPERATOR
#undef UNARYOP_LIST
}
}
// Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
switch (S->getStmtClass()) {
case Stmt::NoStmtClass:
@ -592,7 +509,7 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) \
case Stmt::CLASS##Class: \
DISPATCH_STMT(CLASS, CLASS, S);
return TRAVERSE_STMT_BASE(CLASS, CLASS, S, Queue);
#include "clang/AST/StmtNodes.inc"
}
@ -603,23 +520,44 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
template <typename Derived>
bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) {
// In pre-order traversal mode, each Traverse##STMT method is responsible for
// calling WalkUpFrom. Therefore, if the user overrides Traverse##STMT and
// does not call the default implementation, the WalkUpFrom callback is not
// called. Post-order traversal mode should provide the same behavior
// regarding method overrides.
//
// In post-order traversal mode the Traverse##STMT method, when it receives a
// DataRecursionQueue, can't call WalkUpFrom after traversing children because
// it only enqueues the children and does not traverse them. TraverseStmt
// traverses the enqueued children, and we call WalkUpFrom here.
//
// However, to make pre-order and post-order modes identical with regards to
// whether they call WalkUpFrom at all, we call WalkUpFrom if and only if the
// user did not override the Traverse##STMT method. We implement the override
// check with isSameMethod calls below.
switch (S->getStmtClass()) {
case Stmt::NoStmtClass:
break;
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) \
case Stmt::CLASS##Class: \
TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); break;
if (::clang::detail::isSameMethod(&RecursiveASTVisitor::Traverse##CLASS, \
&Derived::Traverse##CLASS)) { \
TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); \
} \
break;
#define INITLISTEXPR(CLASS, PARENT) \
case Stmt::CLASS##Class: \
{ \
if (::clang::detail::isSameMethod(&RecursiveASTVisitor::Traverse##CLASS, \
&Derived::Traverse##CLASS)) { \
auto ILE = static_cast<CLASS *>(S); \
if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE) \
TRY_TO(WalkUpFrom##CLASS(Syn)); \
if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm()) \
TRY_TO(WalkUpFrom##CLASS(Sem)); \
break; \
}
} \
break;
#include "clang/AST/StmtNodes.inc"
}
@ -669,9 +607,6 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S,
return true;
}
#define DISPATCH(NAME, CLASS, VAR) \
return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
if (T.isNull())
@ -681,7 +616,8 @@ bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
#define ABSTRACT_TYPE(CLASS, BASE)
#define TYPE(CLASS, BASE) \
case Type::CLASS: \
DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr()));
return getDerived().Traverse##CLASS##Type( \
static_cast<CLASS##Type *>(const_cast<Type *>(T.getTypePtr())));
#include "clang/AST/TypeNodes.inc"
}
@ -731,8 +667,6 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
return true;
}
#undef DISPATCH
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
NestedNameSpecifier *NNS) {
@ -1006,6 +940,17 @@ DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); })
DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); })
DEF_TRAVERSE_TYPE(ConstantMatrixType,
{ TRY_TO(TraverseType(T->getElementType())); })
DEF_TRAVERSE_TYPE(DependentSizedMatrixType, {
if (T->getRowExpr())
TRY_TO(TraverseStmt(T->getRowExpr()));
if (T->getColumnExpr())
TRY_TO(TraverseStmt(T->getColumnExpr()));
TRY_TO(TraverseType(T->getElementType()));
})
DEF_TRAVERSE_TYPE(FunctionNoProtoType,
{ TRY_TO(TraverseType(T->getReturnType())); })
@ -1115,6 +1060,10 @@ DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); })
DEF_TRAVERSE_TYPE(ExtIntType, {})
DEF_TRAVERSE_TYPE(DependentExtIntType,
{ TRY_TO(TraverseStmt(T->getNumBitsExpr())); })
#undef DEF_TRAVERSE_TYPE
// ----------------- TypeLoc traversal -----------------
@ -1127,10 +1076,17 @@ DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); })
#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \
template <typename Derived> \
bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \
if (getDerived().shouldWalkTypesOfTypeLocs()) \
TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \
TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
if (!getDerived().shouldTraversePostOrder()) { \
TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
if (getDerived().shouldWalkTypesOfTypeLocs()) \
TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \
} \
{ CODE; } \
if (getDerived().shouldTraversePostOrder()) { \
TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
if (getDerived().shouldWalkTypesOfTypeLocs()) \
TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \
} \
return true; \
}
@ -1199,22 +1155,22 @@ bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
return TraverseArrayTypeLocHelper(TL);
TRY_TO(TraverseArrayTypeLocHelper(TL));
})
DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
return TraverseArrayTypeLocHelper(TL);
TRY_TO(TraverseArrayTypeLocHelper(TL));
})
DEF_TRAVERSE_TYPELOC(VariableArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
return TraverseArrayTypeLocHelper(TL);
TRY_TO(TraverseArrayTypeLocHelper(TL));
})
DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
return TraverseArrayTypeLocHelper(TL);
TRY_TO(TraverseArrayTypeLocHelper(TL));
})
DEF_TRAVERSE_TYPELOC(DependentAddressSpaceType, {
@ -1247,6 +1203,18 @@ DEF_TRAVERSE_TYPELOC(ExtVectorType, {
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
DEF_TRAVERSE_TYPELOC(ConstantMatrixType, {
TRY_TO(TraverseStmt(TL.getAttrRowOperand()));
TRY_TO(TraverseStmt(TL.getAttrColumnOperand()));
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
DEF_TRAVERSE_TYPELOC(DependentSizedMatrixType, {
TRY_TO(TraverseStmt(TL.getAttrRowOperand()));
TRY_TO(TraverseStmt(TL.getAttrColumnOperand()));
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
DEF_TRAVERSE_TYPELOC(FunctionNoProtoType,
{ TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); })
@ -1378,6 +1346,11 @@ DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
DEF_TRAVERSE_TYPELOC(ExtIntType, {})
DEF_TRAVERSE_TYPELOC(DependentExtIntType, {
TRY_TO(TraverseStmt(TL.getTypePtr()->getNumBitsExpr()));
})
#undef DEF_TRAVERSE_TYPELOC
// ----------------- Decl traversal -----------------
@ -1986,6 +1959,8 @@ DEF_TRAVERSE_DECL(BindingDecl, {
DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); })
DEF_TRAVERSE_DECL(MSGuidDecl, {})
DEF_TRAVERSE_DECL(FieldDecl, {
TRY_TO(TraverseDeclaratorHelper(D));
if (D->isBitField())
@ -2062,11 +2037,11 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
}
}
bool VisitBody = D->isThisDeclarationADefinition();
// If a method is set to default outside the class definition the compiler
// generates the method body and adds it to the AST.
if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
VisitBody &= !MD->isDefaulted() || getDerived().shouldVisitImplicitCode();
bool VisitBody =
D->isThisDeclarationADefinition() &&
// Don't visit the function body if the function definition is generated
// by clang.
(!D->isDefaulted() || getDerived().shouldVisitImplicitCode());
if (VisitBody) {
TRY_TO(TraverseStmt(D->getBody())); // Function body.
@ -2179,8 +2154,13 @@ DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {})
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \
} \
} \
if (!Queue && ReturnValue && getDerived().shouldTraversePostOrder()) \
/* Call WalkUpFrom if TRY_TO_TRAVERSE_OR_ENQUEUE_STMT has traversed the \
* children already. If TRY_TO_TRAVERSE_OR_ENQUEUE_STMT only enqueued the \
* children, PostVisitStmt will call WalkUpFrom after we are done visiting \
* children. */ \
if (!Queue && ReturnValue && getDerived().shouldTraversePostOrder()) { \
TRY_TO(WalkUpFrom##STMT(S)); \
} \
return ReturnValue; \
}
@ -2314,6 +2294,10 @@ DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXAddrspaceCastExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXConstCastExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
@ -2347,6 +2331,9 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
for (Stmt *SubStmt : S->children()) {
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt);
}
if (!Queue && getDerived().shouldTraversePostOrder())
TRY_TO(WalkUpFromInitListExpr(S));
}
return true;
}
@ -2543,7 +2530,10 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
DEF_TRAVERSE_STMT(MatrixSubscriptExpr, {})
DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})
DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {})
DEF_TRAVERSE_STMT(OMPIteratorExpr, {})
DEF_TRAVERSE_STMT(BlockExpr, {
TRY_TO(TraverseDecl(S->getBlockDecl()));
@ -2661,6 +2651,7 @@ DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, {
})
DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
DEF_TRAVERSE_STMT(TypoExpr, {})
DEF_TRAVERSE_STMT(RecoveryExpr, {})
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
// These operators (all of them) do not need any action except
@ -2842,6 +2833,12 @@ DEF_TRAVERSE_STMT(OMPCancelDirective,
DEF_TRAVERSE_STMT(OMPFlushDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPDepobjDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPScanDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
DEF_TRAVERSE_STMT(OMPOrderedDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@ -2941,16 +2938,15 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
if (!C)
return true;
switch (C->getClauseKind()) {
#define OPENMP_CLAUSE(Name, Class) \
case OMPC_##Name: \
#define OMP_CLAUSE_CLASS(Enum, Str, Class) \
case llvm::omp::Clause::Enum: \
TRY_TO(Visit##Class(static_cast<Class *>(C))); \
break;
#include "clang/Basic/OpenMPKinds.def"
case OMPC_threadprivate:
case OMPC_uniform:
case OMPC_device_type:
case OMPC_match:
case OMPC_unknown:
#define OMP_CLAUSE_NO_CLASS(Enum, Str) \
case llvm::omp::Clause::Enum: \
break;
#include "llvm/Frontend/OpenMP/OMPKinds.def"
default:
break;
}
return true;
@ -3121,6 +3117,26 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAcqRelClause(OMPAcqRelClause *) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPReleaseClause(OMPReleaseClause *) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPRelaxedClause(OMPRelaxedClause *) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
return true;
@ -3136,6 +3152,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDestroyClause(OMPDestroyClause *) {
return true;
}
template <typename Derived>
template <typename T>
bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
@ -3145,6 +3166,20 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPInclusiveClause(
OMPInclusiveClause *C) {
TRY_TO(VisitOMPClauseList(C));
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPExclusiveClause(
OMPExclusiveClause *C) {
TRY_TO(VisitOMPClauseList(C));
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
TRY_TO(VisitOMPClauseList(C));
@ -3272,6 +3307,17 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
for (auto *E : C->reduction_ops()) {
TRY_TO(TraverseStmt(E));
}
if (C->getModifier() == OMPC_REDUCTION_inscan) {
for (auto *E : C->copy_ops()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->copy_array_temps()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->copy_array_elems()) {
TRY_TO(TraverseStmt(E));
}
}
return true;
}
@ -3327,6 +3373,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDepobjClause(OMPDepobjClause *C) {
TRY_TO(TraverseStmt(C->getDepobj()));
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
TRY_TO(VisitOMPClauseList(C));
@ -3425,6 +3477,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPUseDevicePtrClause(
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPUseDeviceAddrClause(
OMPUseDeviceAddrClause *C) {
TRY_TO(VisitOMPClauseList(C));
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPIsDevicePtrClause(
OMPIsDevicePtrClause *C) {
@ -3442,6 +3501,37 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNontemporalClause(
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPOrderClause(OMPOrderClause *) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDetachClause(OMPDetachClause *C) {
TRY_TO(TraverseStmt(C->getEventHandler()));
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPUsesAllocatorsClause(
OMPUsesAllocatorsClause *C) {
for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
const OMPUsesAllocatorsClause::Data Data = C->getAllocatorData(I);
TRY_TO(TraverseStmt(Data.Allocator));
TRY_TO(TraverseStmt(Data.AllocatorTraits));
}
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAffinityClause(
OMPAffinityClause *C) {
TRY_TO(TraverseStmt(C->getModifier()));
for (Expr *E : C->varlists())
TRY_TO(TraverseStmt(E));
return true;
}
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm

View file

@ -14,12 +14,14 @@
#define LLVM_CLANG_AST_STMT_H
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/StmtIterator.h"
#include "clang/Basic/CapturedStmt.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
@ -98,14 +100,8 @@ protected:
/// The statement class.
unsigned sClass : 8;
/// This bit is set only for the Stmts that are the structured-block of
/// OpenMP executable directives. Directives that have a structured block
/// are called "non-standalone" directives.
/// I.e. those returned by OMPExecutableDirective::getStructuredBlock().
unsigned IsOMPStructuredBlock : 1;
};
enum { NumStmtBits = 9 };
enum { NumStmtBits = 8 };
class NullStmtBitfields {
friend class ASTStmtReader;
@ -315,12 +311,9 @@ protected:
unsigned ValueKind : 2;
unsigned ObjectKind : 3;
unsigned TypeDependent : 1;
unsigned ValueDependent : 1;
unsigned InstantiationDependent : 1;
unsigned ContainsUnexpandedParameterPack : 1;
unsigned /*ExprDependence*/ Dependent : llvm::BitWidth<ExprDependence>;
};
enum { NumExprBits = NumStmtBits + 9 };
enum { NumExprBits = NumStmtBits + 5 + llvm::BitWidth<ExprDependence> };
class ConstantExprBitfields {
friend class ASTStmtReader;
@ -329,24 +322,27 @@ protected:
unsigned : NumExprBits;
/// The kind of result that is trail-allocated.
/// The kind of result that is tail-allocated.
unsigned ResultKind : 2;
/// Kind of Result as defined by APValue::Kind
/// The kind of Result as defined by APValue::Kind.
unsigned APValueKind : 4;
/// When ResultKind == RSK_Int64. whether the trail-allocated integer is
/// signed.
/// When ResultKind == RSK_Int64, true if the tail-allocated integer is
/// unsigned.
unsigned IsUnsigned : 1;
/// When ResultKind == RSK_Int64. the BitWidth of the trail-allocated
/// integer. 7 bits because it is the minimal number of bit to represent a
/// value from 0 to 64 (the size of the trail-allocated number).
/// When ResultKind == RSK_Int64. the BitWidth of the tail-allocated
/// integer. 7 bits because it is the minimal number of bits to represent a
/// value from 0 to 64 (the size of the tail-allocated integer).
unsigned BitWidth : 7;
/// When ResultKind == RSK_APValue. Wether the ASTContext will cleanup the
/// destructor on the trail-allocated APValue.
/// When ResultKind == RSK_APValue, true if the ASTContext will cleanup the
/// tail-allocated APValue.
unsigned HasCleanup : 1;
/// True if this ConstantExpr was created for immediate invocation.
unsigned IsImmediateInvocation : 1;
};
class PredefinedExprBitfields {
@ -431,6 +427,11 @@ protected:
unsigned Opc : 5;
unsigned CanOverflow : 1;
//
/// This is only meaningful for operations on floating point
/// types when additional values need to be in trailing storage.
/// It is 0 otherwise.
unsigned HasFPFeatures : 1;
SourceLocation Loc;
};
@ -444,8 +445,9 @@ protected:
unsigned IsType : 1; // true if operand is a type, false if an expression.
};
class ArraySubscriptExprBitfields {
class ArrayOrMatrixSubscriptExprBitfields {
friend class ArraySubscriptExpr;
friend class MatrixSubscriptExpr;
unsigned : NumExprBits;
@ -529,8 +531,9 @@ protected:
unsigned Opc : 6;
/// This is only meaningful for operations on floating point
/// types and 0 otherwise.
unsigned FPFeatures : 3;
/// types when additional values need to be in trailing storage.
/// It is 0 otherwise.
unsigned HasFPFeatures : 1;
SourceLocation OpLoc;
};
@ -611,9 +614,6 @@ protected:
/// 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 CXXRewrittenBinaryOperatorBitfields {
@ -772,8 +772,10 @@ protected:
/// the trait evaluated true or false.
unsigned Value : 1;
/// The number of arguments to this type trait.
unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
/// The number of arguments to this type trait. According to [implimits]
/// 8 bits would be enough, but we require (and test for) at least 16 bits
/// to mirror FunctionType.
unsigned NumArgs;
};
class DependentScopeDeclRefExprBitfields {
@ -922,6 +924,28 @@ protected:
SourceLocation NameLoc;
};
class LambdaExprBitfields {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend class LambdaExpr;
unsigned : NumExprBits;
/// The default capture kind, which is a value of type
/// LambdaCaptureDefault.
unsigned CaptureDefault : 2;
/// Whether this lambda had an explicit parameter list vs. an
/// implicit (and empty) parameter list.
unsigned ExplicitParams : 1;
/// Whether this lambda had the result type explicitly specified.
unsigned ExplicitResultType : 1;
/// The number of captures.
unsigned NumCaptures : 16;
};
class RequiresExprBitfields {
friend class ASTStmtReader;
friend class ASTStmtWriter;
@ -997,7 +1021,7 @@ protected:
CharacterLiteralBitfields CharacterLiteralBits;
UnaryOperatorBitfields UnaryOperatorBits;
UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits;
ArraySubscriptExprBitfields ArraySubscriptExprBits;
ArrayOrMatrixSubscriptExprBitfields ArrayOrMatrixSubscriptExprBits;
CallExprBitfields CallExprBits;
MemberExprBitfields MemberExprBits;
CastExprBitfields CastExprBits;
@ -1034,6 +1058,7 @@ protected:
UnresolvedMemberExprBitfields UnresolvedMemberExprBits;
CXXNoexceptExprBitfields CXXNoexceptExprBits;
SubstNonTypeTemplateParmExprBitfields SubstNonTypeTemplateParmExprBits;
LambdaExprBitfields LambdaExprBits;
RequiresExprBitfields RequiresExprBits;
// C++ Coroutines TS expressions
@ -1117,7 +1142,6 @@ public:
static_assert(sizeof(*this) % alignof(void *) == 0,
"Insufficient alignment!");
StmtBits.sClass = SC;
StmtBits.IsOMPStructuredBlock = false;
if (StatisticsEnabled) Stmt::addStmtClass(SC);
}
@ -1127,11 +1151,6 @@ public:
const char *getStmtClassName() const;
bool isOMPStructuredBlock() const { return StmtBits.IsOMPStructuredBlock; }
void setIsOMPStructuredBlock(bool IsOMPStructuredBlock) {
StmtBits.IsOMPStructuredBlock = IsOMPStructuredBlock;
}
/// SourceLocation tokens are not useful in isolation - they are low level
/// value objects created/interpreted by SourceManager. We assume AST
/// clients will have a pointer to the respective SourceManager.
@ -1147,9 +1166,7 @@ public:
/// Dumps the specified AST fragment and all subtrees to
/// \c llvm::errs().
void dump() const;
void dump(SourceManager &SM) const;
void dump(raw_ostream &OS, SourceManager &SM) const;
void dump(raw_ostream &OS) const;
void dump(raw_ostream &OS, const ASTContext &Context) const;
/// \return Unique reproducible object identifier
int64_t getID(const ASTContext &Context) const;
@ -2260,6 +2277,8 @@ class WhileStmt final : public Stmt,
enum { VarOffset = 0, BodyOffsetFromCond = 1 };
enum { NumMandatoryStmtPtr = 2 };
SourceLocation LParenLoc, RParenLoc;
unsigned varOffset() const { return VarOffset; }
unsigned condOffset() const { return VarOffset + hasVarStorage(); }
unsigned bodyOffset() const { return condOffset() + BodyOffsetFromCond; }
@ -2270,7 +2289,8 @@ class WhileStmt final : public Stmt,
/// Build a while statement.
WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, Stmt *Body,
SourceLocation WL);
SourceLocation WL, SourceLocation LParenLoc,
SourceLocation RParenLoc);
/// Build an empty while statement.
explicit WhileStmt(EmptyShell Empty, bool HasVar);
@ -2278,7 +2298,8 @@ class WhileStmt final : public Stmt,
public:
/// Create a while statement.
static WhileStmt *Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
Stmt *Body, SourceLocation WL);
Stmt *Body, SourceLocation WL,
SourceLocation LParenLoc, SourceLocation RParenLoc);
/// Create an empty while statement optionally with storage for
/// a condition variable.
@ -2342,6 +2363,11 @@ public:
SourceLocation getWhileLoc() const { return WhileStmtBits.WhileLoc; }
void setWhileLoc(SourceLocation L) { WhileStmtBits.WhileLoc = L; }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getBeginLoc() const { return getWhileLoc(); }
SourceLocation getEndLoc() const LLVM_READONLY {
return getBody()->getEndLoc();
@ -3044,7 +3070,7 @@ public:
}
IdentifierInfo *getLabelIdentifier(unsigned i) const {
return Names[i + NumInputs];
return Names[i + NumOutputs + NumInputs];
}
AddrLabelExpr *getLabelExpr(unsigned i) const;
@ -3055,11 +3081,11 @@ public:
using labels_const_range = llvm::iterator_range<const_labels_iterator>;
labels_iterator begin_labels() {
return &Exprs[0] + NumInputs;
return &Exprs[0] + NumOutputs + NumInputs;
}
labels_iterator end_labels() {
return &Exprs[0] + NumInputs + NumLabels;
return &Exprs[0] + NumOutputs + NumInputs + NumLabels;
}
labels_range labels() {
@ -3067,11 +3093,11 @@ public:
}
const_labels_iterator begin_labels() const {
return &Exprs[0] + NumInputs;
return &Exprs[0] + NumOutputs + NumInputs;
}
const_labels_iterator end_labels() const {
return &Exprs[0] + NumInputs + NumLabels;
return &Exprs[0] + NumOutputs + NumInputs + NumLabels;
}
labels_const_range labels() const {

View file

@ -356,6 +356,9 @@ public:
///
class OMPParallelDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if the construct has inner cancel directive.
bool HasCancel;
@ -381,6 +384,9 @@ class OMPParallelDirective : public OMPExecutableDirective {
SourceLocation(), NumClauses, 1),
HasCancel(false) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
@ -392,11 +398,14 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement associated with the directive.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPParallelDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
bool HasCancel);
/// Creates an empty directive with the place for \a N clauses.
///
@ -406,6 +415,10 @@ public:
static OMPParallelDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
@ -1258,7 +1271,9 @@ public:
///
class OMPForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if current directive has inner cancel directive.
bool HasCancel;
@ -1286,6 +1301,9 @@ class OMPForDirective : public OMPLoopDirective {
NumClauses),
HasCancel(false) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
@ -1299,13 +1317,15 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if current directive has inner cancel directive.
///
static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs,
bool HasCancel);
Expr *TaskRedRef, bool HasCancel);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
@ -1317,6 +1337,10 @@ public:
static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
@ -1403,6 +1427,9 @@ public:
class OMPSectionsDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if current directive has inner cancel directive.
bool HasCancel;
@ -1429,6 +1456,9 @@ class OMPSectionsDirective : public OMPExecutableDirective {
SourceLocation(), NumClauses, 1),
HasCancel(false) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
@ -1440,11 +1470,14 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if current directive has inner directive.
///
static OMPSectionsDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
bool HasCancel);
/// Creates an empty directive with the place for \a NumClauses
/// clauses.
@ -1455,6 +1488,10 @@ public:
static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
@ -1715,6 +1752,9 @@ public:
class OMPParallelForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if current region has inner cancel directive.
bool HasCancel;
@ -1743,6 +1783,9 @@ class OMPParallelForDirective : public OMPLoopDirective {
SourceLocation(), CollapsedNum, NumClauses),
HasCancel(false) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
@ -1756,12 +1799,15 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if current directive has inner cancel directive.
///
static OMPParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
bool HasCancel);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
@ -1775,6 +1821,10 @@ public:
unsigned CollapsedNum,
EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
@ -1863,6 +1913,10 @@ public:
class OMPParallelMasterDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
OMPParallelMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPParallelMasterDirectiveClass,
@ -1875,6 +1929,9 @@ class OMPParallelMasterDirective : public OMPExecutableDirective {
SourceLocation(), SourceLocation(), NumClauses,
1) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
public:
/// Creates directive with a list of \a Clauses.
///
@ -1883,10 +1940,12 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
///
static OMPParallelMasterDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef);
/// Creates an empty directive with the place for \a NumClauses
/// clauses.
@ -1897,6 +1956,10 @@ public:
static OMPParallelMasterDirective *
CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelMasterDirectiveClass;
}
@ -1914,6 +1977,9 @@ public:
class OMPParallelSectionsDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if current directive has inner cancel directive.
bool HasCancel;
@ -1941,6 +2007,9 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective {
1),
HasCancel(false) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
@ -1952,11 +2021,14 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if current directive has inner cancel directive.
///
static OMPParallelSectionsDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
bool HasCancel);
/// Creates an empty directive with the place for \a NumClauses
/// clauses.
@ -1967,6 +2039,10 @@ public:
static OMPParallelSectionsDirective *
CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
@ -2314,6 +2390,64 @@ public:
}
};
/// This represents '#pragma omp depobj' directive.
///
/// \code
/// #pragma omp depobj(a) depend(in:x,y)
/// \endcode
/// In this example directive '#pragma omp depobj' initializes a depobj object
/// 'a' with dependence type 'in' and a list with 'x' and 'y' locators.
class OMPDepobjDirective final : public OMPExecutableDirective {
friend class ASTStmtReader;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param NumClauses Number of clauses.
///
OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPDepobjDirectiveClass,
llvm::omp::OMPD_depobj, StartLoc, EndLoc,
NumClauses, 0) {}
/// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
explicit OMPDepobjDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPDepobjDirectiveClass,
llvm::omp::OMPD_depobj, SourceLocation(),
SourceLocation(), NumClauses, 0) {}
public:
/// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
///
static OMPDepobjDirective *Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses);
/// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
///
static OMPDepobjDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPDepobjDirectiveClass;
}
};
/// This represents '#pragma omp ordered' directive.
///
/// \code
@ -2747,6 +2881,12 @@ public:
///
class OMPTargetParallelDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if the construct has inner cancel directive.
bool HasCancel = false;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@ -2769,6 +2909,11 @@ class OMPTargetParallelDirective : public OMPExecutableDirective {
SourceLocation(), SourceLocation(), NumClauses,
/*NumChildren=*/1) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// Creates directive with a list of \a Clauses.
///
@ -2777,10 +2922,14 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPTargetParallelDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
bool HasCancel);
/// Creates an empty directive with the place for \a NumClauses
/// clauses.
@ -2791,6 +2940,13 @@ public:
static OMPTargetParallelDirective *
CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTargetParallelDirectiveClass;
}
@ -2808,6 +2964,9 @@ public:
class OMPTargetParallelForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if current region has inner cancel directive.
bool HasCancel;
@ -2837,6 +2996,9 @@ class OMPTargetParallelForDirective : public OMPLoopDirective {
SourceLocation(), CollapsedNum, NumClauses),
HasCancel(false) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
@ -2850,12 +3012,15 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if current directive has inner cancel directive.
///
static OMPTargetParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
bool HasCancel);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
@ -2869,6 +3034,10 @@ public:
unsigned CollapsedNum,
EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
@ -3070,6 +3239,9 @@ public:
///
class OMPTaskLoopDirective : public OMPLoopDirective {
friend class ASTStmtReader;
/// true if the construct has inner cancel directive.
bool HasCancel;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@ -3081,7 +3253,8 @@ class OMPTaskLoopDirective : public OMPLoopDirective {
unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPTaskLoopDirectiveClass,
llvm::omp::OMPD_taskloop, StartLoc, EndLoc,
CollapsedNum, NumClauses) {}
CollapsedNum, NumClauses),
HasCancel(false) {}
/// Build an empty directive.
///
@ -3091,7 +3264,11 @@ class OMPTaskLoopDirective : public OMPLoopDirective {
explicit OMPTaskLoopDirective(unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPTaskLoopDirectiveClass,
llvm::omp::OMPD_taskloop, SourceLocation(),
SourceLocation(), CollapsedNum, NumClauses) {}
SourceLocation(), CollapsedNum, NumClauses),
HasCancel(false) {}
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// Creates directive with a list of \a Clauses.
@ -3103,11 +3280,12 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPTaskLoopDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
@ -3120,6 +3298,9 @@ public:
unsigned NumClauses,
unsigned CollapsedNum, EmptyShell);
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTaskLoopDirectiveClass;
}
@ -3203,6 +3384,9 @@ public:
///
class OMPMasterTaskLoopDirective : public OMPLoopDirective {
friend class ASTStmtReader;
/// true if the construct has inner cancel directive.
bool HasCancel;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@ -3214,7 +3398,8 @@ class OMPMasterTaskLoopDirective : public OMPLoopDirective {
unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass,
llvm::omp::OMPD_master_taskloop, StartLoc, EndLoc,
CollapsedNum, NumClauses) {}
CollapsedNum, NumClauses),
HasCancel(false) {}
/// Build an empty directive.
///
@ -3225,7 +3410,11 @@ class OMPMasterTaskLoopDirective : public OMPLoopDirective {
unsigned NumClauses)
: OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass,
llvm::omp::OMPD_master_taskloop, SourceLocation(),
SourceLocation(), CollapsedNum, NumClauses) {}
SourceLocation(), CollapsedNum, NumClauses),
HasCancel(false) {}
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// Creates directive with a list of \a Clauses.
@ -3237,11 +3426,12 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPMasterTaskLoopDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
@ -3255,6 +3445,9 @@ public:
unsigned CollapsedNum,
EmptyShell);
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPMasterTaskLoopDirectiveClass;
}
@ -3339,6 +3532,9 @@ public:
///
class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
friend class ASTStmtReader;
/// true if the construct has inner cancel directive.
bool HasCancel;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@ -3351,7 +3547,8 @@ class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass,
llvm::omp::OMPD_parallel_master_taskloop, StartLoc,
EndLoc, CollapsedNum, NumClauses) {}
EndLoc, CollapsedNum, NumClauses),
HasCancel(false) {}
/// Build an empty directive.
///
@ -3363,7 +3560,11 @@ class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
: OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass,
llvm::omp::OMPD_parallel_master_taskloop,
SourceLocation(), SourceLocation(), CollapsedNum,
NumClauses) {}
NumClauses),
HasCancel(false) {}
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// Creates directive with a list of \a Clauses.
@ -3375,11 +3576,12 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPParallelMasterTaskLoopDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
@ -3393,6 +3595,9 @@ public:
unsigned CollapsedNum,
EmptyShell);
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass;
}
@ -3605,6 +3810,9 @@ public:
///
class OMPDistributeParallelForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if the construct has inner cancel directive.
bool HasCancel = false;
@ -3636,6 +3844,9 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective {
NumClauses),
HasCancel(false) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
@ -3649,12 +3860,15 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPDistributeParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
bool HasCancel);
/// Creates an empty directive with the place
/// for \a NumClauses clauses.
@ -3668,6 +3882,10 @@ public:
unsigned CollapsedNum,
EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
@ -4170,6 +4388,9 @@ public:
///
class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if the construct has inner cancel directive.
bool HasCancel = false;
@ -4202,6 +4423,9 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
NumClauses),
HasCancel(false) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
@ -4215,12 +4439,15 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPTeamsDistributeParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
bool HasCancel);
/// Creates an empty directive with the place for \a NumClauses clauses.
///
@ -4232,6 +4459,10 @@ public:
CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
@ -4379,6 +4610,9 @@ public:
class OMPTargetTeamsDistributeParallelForDirective final
: public OMPLoopDirective {
friend class ASTStmtReader;
/// Special reference expression for handling task reduction. Used to store
/// the taskgroup descriptor returned by the runtime functions.
Expr *TaskRedRef = nullptr;
/// true if the construct has inner cancel directive.
bool HasCancel = false;
@ -4412,6 +4646,9 @@ class OMPTargetTeamsDistributeParallelForDirective final
SourceLocation(), SourceLocation(), CollapsedNum, NumClauses),
HasCancel(false) {}
/// Sets special task reduction descriptor.
void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; }
/// Set cancel state.
void setHasCancel(bool Has) { HasCancel = Has; }
@ -4425,12 +4662,15 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
/// \param TaskRedRef Task reduction special reference expression to handle
/// taskgroup descriptor.
/// \param HasCancel true if this directive has inner cancel directive.
///
static OMPTargetTeamsDistributeParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
bool HasCancel);
/// Creates an empty directive with the place for \a NumClauses clauses.
///
@ -4442,6 +4682,10 @@ public:
CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
EmptyShell);
/// Returns special task reduction reference expression.
Expr *getTaskReductionRefExpr() { return TaskRedRef; }
const Expr *getTaskReductionRefExpr() const { return TaskRedRef; }
/// Return true if current directive has inner cancel directive.
bool hasCancel() const { return HasCancel; }
@ -4594,6 +4838,63 @@ public:
}
};
/// This represents '#pragma omp scan' directive.
///
/// \code
/// #pragma omp scan inclusive(a)
/// \endcode
/// In this example directive '#pragma omp scan' has clause 'inclusive' with
/// list item 'a'.
class OMPScanDirective final : public OMPExecutableDirective {
friend class ASTStmtReader;
/// Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param NumClauses Number of clauses.
///
OMPScanDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPScanDirectiveClass,
llvm::omp::OMPD_scan, StartLoc, EndLoc,
NumClauses, 0) {}
/// Build an empty directive.
///
/// \param NumClauses Number of clauses.
///
explicit OMPScanDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPScanDirectiveClass,
llvm::omp::OMPD_scan, SourceLocation(),
SourceLocation(), NumClauses, 0) {}
public:
/// Creates directive with a list of \a Clauses.
///
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses (only single OMPFlushClause clause is
/// allowed).
///
static OMPScanDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses);
/// Creates an empty directive with the place for \a NumClauses
/// clauses.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
///
static OMPScanDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPScanDirectiveClass;
}
};
} // end namespace clang
#endif

View file

@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
#define LLVM_CLANG_AST_TEMPLATEBASE_H
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@ -81,8 +82,7 @@ public:
/// The template argument is an expression, and we've not resolved it to one
/// of the other forms yet, either because it's dependent or because we're
/// representing a non-canonical template argument (for instance, in a
/// TemplateSpecializationType). Also used to represent a non-dependent
/// __uuidof expression (a Microsoft extension).
/// TemplateSpecializationType).
Expression,
/// The template argument is actually a parameter pack. Arguments are stored
@ -236,6 +236,8 @@ public:
/// Determine whether this template argument has no value.
bool isNull() const { return getKind() == Null; }
TemplateArgumentDependence getDependence() const;
/// Whether this template argument is dependent on a template
/// parameter such that its result can change from one instantiation to
/// another.
@ -666,11 +668,13 @@ struct alignas(void *) ASTTemplateKWAndArgsInfo {
void initializeFrom(SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &List,
TemplateArgumentLoc *OutArgArray);
// FIXME: The parameter Deps is the result populated by this method, the
// caller doesn't need it since it is populated by computeDependence. remove
// it.
void initializeFrom(SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &List,
TemplateArgumentLoc *OutArgArray, bool &Dependent,
bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack);
TemplateArgumentLoc *OutArgArray,
TemplateArgumentDependence &Deps);
void initializeFrom(SourceLocation TemplateKWLoc);
void copyInto(const TemplateArgumentLoc *ArgArray,

View file

@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_AST_TEMPLATENAME_H
#define LLVM_CLANG_AST_TEMPLATENAME_H
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/FoldingSet.h"
@ -295,6 +296,8 @@ public:
/// the template, including any default template arguments.
TemplateName getNameToSubstitute() const;
TemplateNameDependence getDependence() const;
/// Determines whether this is a dependent template name.
bool isDependent() const;
@ -559,7 +562,7 @@ struct PointerLikeTypeTraits<clang::TemplateName> {
}
// No bits are available!
enum { NumLowBitsAvailable = 0 };
static constexpr int NumLowBitsAvailable = 0;
};
} // namespace llvm.

View file

@ -22,10 +22,13 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TemplateArgumentVisitor.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeVisitor.h"
namespace clang {
class APValue;
class TextTreeStructure {
raw_ostream &OS;
const bool ShowColors;
@ -68,7 +71,7 @@ public:
// We need to capture an owning-string in the lambda because the lambda
// is invoked in a deferred manner.
std::string LabelStr = Label;
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:
@ -139,19 +142,29 @@ class TextNodeDumper
const char *LastLocFilename = "";
unsigned LastLocLine = ~0U;
const SourceManager *SM;
/// \p Context, \p SM, and \p Traits can be null. This is because we want
/// to be able to call \p dump() in a debugger without having to pass the
/// \p ASTContext to \p dump. Not all parts of the AST dump output will be
/// available without the \p ASTContext.
const ASTContext *Context = nullptr;
const SourceManager *SM = nullptr;
/// The policy to use for printing; can be defaulted.
PrintingPolicy PrintPolicy;
PrintingPolicy PrintPolicy = LangOptions();
const comments::CommandTraits *Traits;
const comments::CommandTraits *Traits = nullptr;
const char *getCommandName(unsigned CommandID);
void dumpAPValueChildren(const APValue &Value, QualType Ty,
const APValue &(*IdxToChildFun)(const APValue &,
unsigned),
unsigned NumChildren, StringRef LabelSingular,
StringRef LabelPlurial);
public:
TextNodeDumper(raw_ostream &OS, bool ShowColors, const SourceManager *SM,
const PrintingPolicy &PrintPolicy,
const comments::CommandTraits *Traits);
TextNodeDumper(raw_ostream &OS, const ASTContext &Context, bool ShowColors);
TextNodeDumper(raw_ostream &OS, bool ShowColors);
void Visit(const comments::Comment *C, const comments::FullComment *FC);
@ -176,6 +189,8 @@ public:
void Visit(const GenericSelectionExpr::ConstAssociation &A);
void Visit(const APValue &Value, QualType Ty);
void dumpPointer(const void *Ptr);
void dumpLocation(SourceLocation Loc);
void dumpSourceRange(SourceRange R);
@ -184,6 +199,7 @@ public:
void dumpBareDeclRef(const Decl *D);
void dumpName(const NamedDecl *ND);
void dumpAccessSpecifier(AccessSpecifier AS);
void dumpCleanupObject(const ExprWithCleanups::CleanupObject &C);
void dumpDeclRef(const Decl *D, StringRef Label = {});
@ -230,6 +246,7 @@ public:
void VisitCaseStmt(const CaseStmt *Node);
void VisitConstantExpr(const ConstantExpr *Node);
void VisitCallExpr(const CallExpr *Node);
void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node);
void VisitCastExpr(const CastExpr *Node);
void VisitImplicitCastExpr(const ImplicitCastExpr *Node);
void VisitDeclRefExpr(const DeclRefExpr *Node);
@ -257,6 +274,9 @@ public:
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
void VisitCXXNewExpr(const CXXNewExpr *Node);
void VisitCXXDeleteExpr(const CXXDeleteExpr *Node);
void VisitTypeTraitExpr(const TypeTraitExpr *Node);
void VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node);
void VisitExpressionTraitExpr(const ExpressionTraitExpr *Node);
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
void VisitExprWithCleanups(const ExprWithCleanups *Node);
void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
@ -273,6 +293,7 @@ public:
void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node);
void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node);
void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node);
void VisitOMPIteratorExpr(const OMPIteratorExpr *Node);
void VisitRValueReferenceType(const ReferenceType *T);
void VisitArrayType(const ArrayType *T);

File diff suppressed because it is too large Load diff

View file

@ -1735,6 +1735,7 @@ public:
void initializeLocal(ASTContext &Context, SourceLocation loc) {
setAttrNameLoc(loc);
setAttrOperandParensRange(loc);
setAttrOperandParensRange(SourceRange(loc));
setAttrExprOperand(getTypePtr()->getAddrSpaceExpr());
}
@ -1774,6 +1775,68 @@ class DependentSizedExtVectorTypeLoc :
DependentSizedExtVectorType> {
};
struct MatrixTypeLocInfo {
SourceLocation AttrLoc;
SourceRange OperandParens;
Expr *RowOperand;
Expr *ColumnOperand;
};
class MatrixTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, MatrixTypeLoc,
MatrixType, MatrixTypeLocInfo> {
public:
/// The location of the attribute name, i.e.
/// float __attribute__((matrix_type(4, 2)))
/// ^~~~~~~~~~~~~~~~~
SourceLocation getAttrNameLoc() const { return getLocalData()->AttrLoc; }
void setAttrNameLoc(SourceLocation loc) { getLocalData()->AttrLoc = loc; }
/// The attribute's row operand, if it has one.
/// float __attribute__((matrix_type(4, 2)))
/// ^
Expr *getAttrRowOperand() const { return getLocalData()->RowOperand; }
void setAttrRowOperand(Expr *e) { getLocalData()->RowOperand = e; }
/// The attribute's column operand, if it has one.
/// float __attribute__((matrix_type(4, 2)))
/// ^
Expr *getAttrColumnOperand() const { return getLocalData()->ColumnOperand; }
void setAttrColumnOperand(Expr *e) { getLocalData()->ColumnOperand = e; }
/// The location of the parentheses around the operand, if there is
/// an operand.
/// float __attribute__((matrix_type(4, 2)))
/// ^ ^
SourceRange getAttrOperandParensRange() const {
return getLocalData()->OperandParens;
}
void setAttrOperandParensRange(SourceRange range) {
getLocalData()->OperandParens = range;
}
SourceRange getLocalSourceRange() const {
SourceRange range(getAttrNameLoc());
range.setEnd(getAttrOperandParensRange().getEnd());
return range;
}
void initializeLocal(ASTContext &Context, SourceLocation loc) {
setAttrNameLoc(loc);
setAttrOperandParensRange(loc);
setAttrRowOperand(nullptr);
setAttrColumnOperand(nullptr);
}
};
class ConstantMatrixTypeLoc
: public InheritingConcreteTypeLoc<MatrixTypeLoc, ConstantMatrixTypeLoc,
ConstantMatrixType> {};
class DependentSizedMatrixTypeLoc
: public InheritingConcreteTypeLoc<MatrixTypeLoc,
DependentSizedMatrixTypeLoc,
DependentSizedMatrixType> {};
// FIXME: location of the '_Complex' keyword.
class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
ComplexTypeLoc,
@ -2450,6 +2513,12 @@ inline T TypeLoc::getAsAdjusted() const {
}
return Cur.getAs<T>();
}
class ExtIntTypeLoc final
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc, ExtIntTypeLoc,
ExtIntType> {};
class DependentExtIntTypeLoc final
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentExtIntTypeLoc,
DependentExtIntType> {};
} // namespace clang

View file

@ -13,7 +13,6 @@
#define LLVM_CLANG_AST_TYPELOCVISITOR_H
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeVisitor.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {

View file

@ -224,6 +224,41 @@ let Class = DependentSizedExtVectorType in {
}]>;
}
let Class = MatrixType in {
def : Property<"elementType", QualType> {
let Read = [{ node->getElementType() }];
}
}
let Class = ConstantMatrixType in {
def : Property<"numRows", UInt32> {
let Read = [{ node->getNumRows() }];
}
def : Property<"numColumns", UInt32> {
let Read = [{ node->getNumColumns() }];
}
def : Creator<[{
return ctx.getConstantMatrixType(elementType, numRows, numColumns);
}]>;
}
let Class = DependentSizedMatrixType in {
def : Property<"rows", ExprRef> {
let Read = [{ node->getRowExpr() }];
}
def : Property<"columns", ExprRef> {
let Read = [{ node->getColumnExpr() }];
}
def : Property<"attributeLoc", SourceLocation> {
let Read = [{ node->getAttributeLoc() }];
}
def : Creator<[{
return ctx.getDependentSizedMatrixType(elementType, rows, columns, attributeLoc);
}]>;
}
let Class = FunctionType in {
def : Property<"returnType", QualType> {
let Read = [{ node->getReturnType() }];
@ -249,13 +284,17 @@ let Class = FunctionType in {
def : Property<"noCfCheck", Bool> {
let Read = [{ node->getExtInfo().getNoCfCheck() }];
}
def : Property<"cmseNSCall", Bool> {
let Read = [{ node->getExtInfo().getCmseNSCall() }];
}
}
let Class = FunctionNoProtoType in {
def : Creator<[{
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
callingConvention, producesResult,
noCallerSavedRegs, noCfCheck);
noCallerSavedRegs, noCfCheck,
cmseNSCall);
return ctx.getFunctionNoProtoType(returnType, extInfo);
}]>;
}
@ -288,7 +327,8 @@ let Class = FunctionProtoType in {
def : Creator<[{
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
callingConvention, producesResult,
noCallerSavedRegs, noCfCheck);
noCallerSavedRegs, noCfCheck,
cmseNSCall);
FunctionProtoType::ExtProtoInfo epi;
epi.ExtInfo = extInfo;
epi.Variadic = variadic;
@ -453,7 +493,9 @@ let Class = TagType in {
let Class = EnumType in {
def : Creator<[{
QualType result = ctx.getEnumType(cast<EnumDecl>(declaration));
const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
if (dependent)
const_cast<Type *>(result.getTypePtr())
->addDependence(TypeDependence::DependentInstantiation);
return result;
}]>;
}
@ -462,7 +504,9 @@ let Class = RecordType in {
def : Creator<[{
auto record = cast<RecordDecl>(declaration);
QualType result = ctx.getRecordType(record);
const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
if (dependent)
const_cast<Type *>(result.getTypePtr())
->addDependence(TypeDependence::DependentInstantiation);
return result;
}]>;
}
@ -605,7 +649,9 @@ let Class = TemplateSpecializationType in {
templateArguments,
*underlyingType);
}
const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
if (dependent)
const_cast<Type *>(result.getTypePtr())
->addDependence(TypeDependence::DependentInstantiation);
return result;
}]>;
}
@ -822,3 +868,28 @@ let Class = PipeType in {
return ctx.getPipeType(elementType, isReadOnly);
}]>;
}
let Class = ExtIntType in {
def : Property<"isUnsigned", Bool> {
let Read = [{ node->isUnsigned() }];
}
def : Property <"numBits", UInt32> {
let Read = [{ node->getNumBits() }];
}
def : Creator<[{
return ctx.getExtIntType(isUnsigned, numBits);
}]>;
}
let Class = DependentExtIntType in {
def : Property<"isUnsigned", Bool> {
let Read = [{ node->isUnsigned() }];
}
def : Property <"numBitsExpr", ExprRef> {
let Read = [{ node->getNumBitsExpr() }];
}
def : Creator<[{
return ctx.getDependentExtIntType(isUnsigned, numBitsExpr);
}]>;
}

View file

@ -238,6 +238,11 @@ public:
typedef llvm::DenseMap<BaseSubobject, AddressPointLocation>
AddressPointsMapTy;
// Mapping between the VTable index and address point index. This is useful
// when you don't care about the base subobjects and only want the address
// point for a given vtable index.
typedef llvm::SmallVector<unsigned, 4> AddressPointsIndexMapTy;
private:
// Stores the component indices of the first component of each virtual table in
// the virtual table group. To save a little memory in the common case where
@ -253,6 +258,9 @@ private:
/// Address points for all vtables.
AddressPointsMapTy AddressPoints;
/// Address points for all vtable indices.
AddressPointsIndexMapTy AddressPointIndices;
public:
VTableLayout(ArrayRef<size_t> VTableIndices,
ArrayRef<VTableComponent> VTableComponents,
@ -277,6 +285,10 @@ public:
return AddressPoints;
}
const AddressPointsIndexMapTy &getAddressPointIndices() const {
return AddressPointIndices;
}
size_t getNumVTables() const {
if (VTableIndices.empty())
return 1;
@ -342,6 +354,9 @@ public:
}
bool IsMicrosoftABI;
/// Determine whether this function should be assigned a vtable slot.
static bool hasVtableSlot(const CXXMethodDecl *MD);
};
class ItaniumVTableContext : public VTableContextBase {
@ -371,7 +386,17 @@ private:
void computeVTableRelatedInformation(const CXXRecordDecl *RD) override;
public:
ItaniumVTableContext(ASTContext &Context);
enum VTableComponentLayout {
/// Components in the vtable are pointers to other structs/functions.
Pointer,
/// Components in the vtable are relative offsets between the vtable and the
/// other structs/functions.
Relative,
};
ItaniumVTableContext(ASTContext &Context,
VTableComponentLayout ComponentLayout = Pointer);
~ItaniumVTableContext() override;
const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) {
@ -402,6 +427,16 @@ public:
static bool classof(const VTableContextBase *VT) {
return !VT->isMicrosoft();
}
VTableComponentLayout getVTableComponentLayout() const {
return ComponentLayout;
}
bool isPointerLayout() const { return ComponentLayout == Pointer; }
bool isRelativeLayout() const { return ComponentLayout == Relative; }
private:
VTableComponentLayout ComponentLayout;
};
/// Holds information about the inheritance path to a virtual base or function

View file

@ -182,10 +182,9 @@ public:
///
/// @{
template <typename T> void match(const T &Node, ASTContext &Context) {
match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
match(clang::DynTypedNode::create(Node), Context);
}
void match(const clang::ast_type_traits::DynTypedNode &Node,
ASTContext &Context);
void match(const clang::DynTypedNode &Node, ASTContext &Context);
/// @}
/// Finds all matches in the given AST.
@ -242,9 +241,8 @@ SmallVector<BoundNodes, 1>
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
template <typename MatcherT>
SmallVector<BoundNodes, 1>
match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
ASTContext &Context);
SmallVector<BoundNodes, 1> match(MatcherT Matcher, const DynTypedNode &Node,
ASTContext &Context);
/// @}
/// Returns the results of matching \p Matcher on the translation unit of
@ -283,9 +281,8 @@ public:
}
template <typename MatcherT>
SmallVector<BoundNodes, 1>
match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
ASTContext &Context) {
SmallVector<BoundNodes, 1> match(MatcherT Matcher, const DynTypedNode &Node,
ASTContext &Context) {
internal::CollectMatchesCallback Callback;
MatchFinder Finder;
Finder.addMatcher(Matcher, &Callback);
@ -296,7 +293,7 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
template <typename MatcherT, typename NodeT>
SmallVector<BoundNodes, 1>
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
return match(Matcher, DynTypedNode::create(Node), Context);
}
template <typename MatcherT>
@ -310,8 +307,8 @@ match(MatcherT Matcher, ASTContext &Context) {
}
inline SmallVector<BoundNodes, 1>
matchDynamic(internal::DynTypedMatcher Matcher,
const ast_type_traits::DynTypedNode &Node, ASTContext &Context) {
matchDynamic(internal::DynTypedMatcher Matcher, const DynTypedNode &Node,
ASTContext &Context) {
internal::CollectMatchesCallback Callback;
MatchFinder Finder;
Finder.addDynamicMatcher(Matcher, &Callback);
@ -323,8 +320,7 @@ template <typename NodeT>
SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher,
const NodeT &Node,
ASTContext &Context) {
return matchDynamic(Matcher, ast_type_traits::DynTypedNode::create(Node),
Context);
return matchDynamic(Matcher, DynTypedNode::create(Node), Context);
}
inline SmallVector<BoundNodes, 1>

View file

@ -47,6 +47,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
@ -59,6 +60,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/ParentMapContext.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
@ -71,6 +73,7 @@
#include "clang/ASTMatchers/ASTMatchersMacros.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
@ -114,7 +117,7 @@ public:
/// Type of mapping from binding identifiers to bound nodes. This type
/// is an associative container with a key type of \c std::string and a value
/// type of \c clang::ast_type_traits::DynTypedNode
/// type of \c clang::DynTypedNode
using IDToNodeMap = internal::BoundNodesMap::IDToNodeMap;
/// Retrieve mapping from binding identifiers to bound nodes.
@ -280,9 +283,10 @@ AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
/// \endcode
///
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc),
std::string, RegExp) {
AST_POLYMORPHIC_MATCHER_REGEX(isExpansionInFileMatching,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt,
TypeLoc),
RegExp) {
auto &SourceManager = Finder->getASTContext().getSourceManager();
auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getBeginLoc());
if (ExpansionLoc.isInvalid()) {
@ -295,8 +299,27 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
}
auto Filename = FileEntry->getName();
llvm::Regex RE(RegExp);
return RE.match(Filename);
return RegExp->match(Filename);
}
/// Matches statements that are (transitively) expanded from the named macro.
/// Does not match if only part of the statement is expanded from that macro or
/// if different parts of the the statement are expanded from different
/// appearances of the macro.
///
/// FIXME: Change to be a polymorphic matcher that works on any syntactic
/// node. There's nothing `Stmt`-specific about it.
AST_MATCHER_P(Stmt, isExpandedFromMacro, llvm::StringRef, MacroName) {
// Verifies that the statement' beginning and ending are both expanded from
// the same instance of the given macro.
auto& Context = Finder->getASTContext();
llvm::Optional<SourceLocation> B =
internal::getExpansionLocOfMacro(MacroName, Node.getBeginLoc(), Context);
if (!B) return false;
llvm::Optional<SourceLocation> E =
internal::getExpansionLocOfMacro(MacroName, Node.getEndLoc(), Context);
if (!E) return false;
return *B == *E;
}
/// Matches declarations.
@ -526,52 +549,72 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
extern const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl>
templateTypeParmDecl;
/// Matches public C++ declarations.
/// Matches public C++ declarations and C++ base specifers that specify public
/// inheritance.
///
/// Given
/// Examples:
/// \code
/// class C {
/// public: int a;
/// public: int a; // fieldDecl(isPublic()) matches 'a'
/// protected: int b;
/// private: int c;
/// };
/// \endcode
/// fieldDecl(isPublic())
/// matches 'int a;'
AST_MATCHER(Decl, isPublic) {
return Node.getAccess() == AS_public;
///
/// \code
/// class Base {};
/// class Derived1 : public Base {}; // matches 'Base'
/// struct Derived2 : Base {}; // matches 'Base'
/// \endcode
AST_POLYMORPHIC_MATCHER(isPublic,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
CXXBaseSpecifier)) {
return getAccessSpecifier(Node) == AS_public;
}
/// Matches protected C++ declarations.
/// Matches protected C++ declarations and C++ base specifers that specify
/// protected inheritance.
///
/// Given
/// Examples:
/// \code
/// class C {
/// public: int a;
/// protected: int b;
/// protected: int b; // fieldDecl(isProtected()) matches 'b'
/// private: int c;
/// };
/// \endcode
/// fieldDecl(isProtected())
/// matches 'int b;'
AST_MATCHER(Decl, isProtected) {
return Node.getAccess() == AS_protected;
///
/// \code
/// class Base {};
/// class Derived : protected Base {}; // matches 'Base'
/// \endcode
AST_POLYMORPHIC_MATCHER(isProtected,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
CXXBaseSpecifier)) {
return getAccessSpecifier(Node) == AS_protected;
}
/// Matches private C++ declarations.
/// Matches private C++ declarations and C++ base specifers that specify private
/// inheritance.
///
/// Given
/// Examples:
/// \code
/// class C {
/// public: int a;
/// protected: int b;
/// private: int c;
/// private: int c; // fieldDecl(isPrivate()) matches 'c'
/// };
/// \endcode
/// fieldDecl(isPrivate())
/// matches 'int c;'
AST_MATCHER(Decl, isPrivate) {
return Node.getAccess() == AS_private;
///
/// \code
/// struct Base {};
/// struct Derived1 : private Base {}; // matches 'Base'
/// class Derived2 : Base {}; // matches 'Base'
/// \endcode
AST_POLYMORPHIC_MATCHER(isPrivate,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
CXXBaseSpecifier)) {
return getAccessSpecifier(Node) == AS_private;
}
/// Matches non-static data members that are bit-fields.
@ -701,13 +744,13 @@ AST_POLYMORPHIC_MATCHER_P(
/// \endcode
/// The matcher
/// \code
/// traverse(ast_type_traits::TK_IgnoreImplicitCastsAndParentheses,
/// traverse(TK_IgnoreImplicitCastsAndParentheses,
/// varDecl(hasInitializer(floatLiteral().bind("init")))
/// )
/// \endcode
/// matches the variable declaration with "init" bound to the "3.0".
template <typename T>
internal::Matcher<T> traverse(ast_type_traits::TraversalKind TK,
internal::Matcher<T> traverse(TraversalKind TK,
const internal::Matcher<T> &InnerMatcher) {
return internal::DynTypedMatcher::constructRestrictedWrapper(
new internal::TraversalMatcher<T>(TK, InnerMatcher),
@ -717,8 +760,7 @@ internal::Matcher<T> traverse(ast_type_traits::TraversalKind TK,
template <typename T>
internal::BindableMatcher<T>
traverse(ast_type_traits::TraversalKind TK,
const internal::BindableMatcher<T> &InnerMatcher) {
traverse(TraversalKind TK, const internal::BindableMatcher<T> &InnerMatcher) {
return internal::BindableMatcher<T>(
internal::DynTypedMatcher::constructRestrictedWrapper(
new internal::TraversalMatcher<T>(TK, InnerMatcher),
@ -728,7 +770,7 @@ traverse(ast_type_traits::TraversalKind TK,
template <typename... T>
internal::TraversalWrapper<internal::VariadicOperatorMatcher<T...>>
traverse(ast_type_traits::TraversalKind TK,
traverse(TraversalKind TK,
const internal::VariadicOperatorMatcher<T...> &InnerMatcher) {
return internal::TraversalWrapper<internal::VariadicOperatorMatcher<T...>>(
TK, InnerMatcher);
@ -738,9 +780,8 @@ template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
typename T, typename ToTypes>
internal::TraversalWrapper<
internal::ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>>
traverse(ast_type_traits::TraversalKind TK,
const internal::ArgumentAdaptingMatcherFuncAdaptor<
ArgumentAdapterT, T, ToTypes> &InnerMatcher) {
traverse(TraversalKind TK, const internal::ArgumentAdaptingMatcherFuncAdaptor<
ArgumentAdapterT, T, ToTypes> &InnerMatcher) {
return internal::TraversalWrapper<
internal::ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T,
ToTypes>>(TK, InnerMatcher);
@ -750,10 +791,8 @@ template <template <typename T, typename P1> class MatcherT, typename P1,
typename ReturnTypesF>
internal::TraversalWrapper<
internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>>
traverse(
ast_type_traits::TraversalKind TK,
const internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>
&InnerMatcher) {
traverse(TraversalKind TK, const internal::PolymorphicMatcherWithParam1<
MatcherT, P1, ReturnTypesF> &InnerMatcher) {
return internal::TraversalWrapper<
internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>>(
TK, InnerMatcher);
@ -763,10 +802,8 @@ template <template <typename T, typename P1, typename P2> class MatcherT,
typename P1, typename P2, typename ReturnTypesF>
internal::TraversalWrapper<
internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>>
traverse(
ast_type_traits::TraversalKind TK,
const internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>
&InnerMatcher) {
traverse(TraversalKind TK, const internal::PolymorphicMatcherWithParam2<
MatcherT, P1, P2, ReturnTypesF> &InnerMatcher) {
return internal::TraversalWrapper<
internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>>(
TK, InnerMatcher);
@ -1194,6 +1231,20 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl>
enumConstantDecl;
/// Matches tag declarations.
///
/// Example matches X, Z, U, S, E
/// \code
/// class X;
/// template<class T> class Z {};
/// struct S {};
/// union U {};
/// enum E {
/// A, B, C
/// };
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, TagDecl> tagDecl;
/// Matches method declarations.
///
/// Example matches y
@ -1823,6 +1874,22 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr>
cxxDeleteExpr;
/// Matches noexcept expressions.
///
/// Given
/// \code
/// bool a() noexcept;
/// bool b() noexcept(true);
/// bool c() noexcept(false);
/// bool d() noexcept(noexcept(a()));
/// bool e = noexcept(b()) || noexcept(c());
/// \endcode
/// cxxNoexceptExpr()
/// matches `noexcept(a())`, `noexcept(b())` and `noexcept(c())`.
/// doesn't match the noexcept specifier in the declarations a, b, c or d.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
cxxNoexceptExpr;
/// Matches array subscript expressions.
///
/// Given
@ -2225,6 +2292,10 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImaginaryLiteral>
imaginaryLiteral;
/// Matches fixed point literals
extern const internal::VariadicDynCastAllOfMatcher<Stmt, FixedPointLiteral>
fixedPointLiteral;
/// Matches user defined literal operator call.
///
/// Example match: "foo"_suffix
@ -2541,13 +2612,11 @@ extern const internal::VariadicOperatorMatcherFunc<
2, std::numeric_limits<unsigned>::max()>
allOf;
/// Matches any node regardless of the submatchers.
/// Matches any node regardless of the submatcher.
///
/// However, \c optionally will generate a result binding for each matching
/// submatcher.
///
/// Useful when additional information which may or may not present about a
/// main matching node is desired.
/// However, \c optionally will retain any bindings generated by the submatcher.
/// Useful when additional information which may or may not present about a main
/// matching node is desired.
///
/// For example, in:
/// \code
@ -2567,9 +2636,7 @@ extern const internal::VariadicOperatorMatcherFunc<
/// member named "bar" in that class.
///
/// Usable as: Any Matcher
extern const internal::VariadicOperatorMatcherFunc<
1, std::numeric_limits<unsigned>::max()>
optionally;
extern const internal::VariadicOperatorMatcherFunc<1, 1> optionally;
/// Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
///
@ -2616,7 +2683,7 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) {
/// Same as unaryExprOrTypeTraitExpr, but only matching
/// alignof.
inline internal::Matcher<Stmt> alignOfExpr(
inline internal::BindableMatcher<Stmt> alignOfExpr(
const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
return stmt(unaryExprOrTypeTraitExpr(
allOf(anyOf(ofKind(UETT_AlignOf), ofKind(UETT_PreferredAlignOf)),
@ -2625,7 +2692,7 @@ inline internal::Matcher<Stmt> alignOfExpr(
/// Same as unaryExprOrTypeTraitExpr, but only matching
/// sizeof.
inline internal::Matcher<Stmt> sizeOfExpr(
inline internal::BindableMatcher<Stmt> sizeOfExpr(
const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
return stmt(unaryExprOrTypeTraitExpr(
allOf(ofKind(UETT_SizeOf), InnerMatcher)));
@ -2646,8 +2713,9 @@ inline internal::Matcher<Stmt> sizeOfExpr(
/// \code
/// namespace a { namespace b { class X; } }
/// \endcode
inline internal::Matcher<NamedDecl> hasName(const std::string &Name) {
return internal::Matcher<NamedDecl>(new internal::HasNameMatcher({Name}));
inline internal::Matcher<NamedDecl> hasName(StringRef Name) {
return internal::Matcher<NamedDecl>(
new internal::HasNameMatcher({std::string(Name)}));
}
/// Matches NamedDecl nodes that have any of the specified names.
@ -2680,11 +2748,9 @@ extern const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
/// \code
/// namespace foo { namespace bar { class X; } }
/// \endcode
AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
assert(!RegExp.empty());
AST_MATCHER_REGEX(NamedDecl, matchesName, RegExp) {
std::string FullNameString = "::" + Node.getQualifiedNameAsString();
llvm::Regex RE(RegExp);
return RE.match(FullNameString);
return RegExp->match(FullNameString);
}
/// Matches overloaded operator names.
@ -2707,14 +2773,30 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
///
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
inline internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
internal::HasOverloadedOperatorNameMatcher, std::vector<std::string>,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>
hasOverloadedOperatorName(StringRef Name) {
return internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name);
internal::HasOverloadedOperatorNameMatcher, std::vector<std::string>,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(
{std::string(Name)});
}
/// Matches overloaded operator names.
///
/// Matches overloaded operator names specified in strings without the
/// "operator" prefix: e.g. "<<".
///
/// hasAnyOverloadesOperatorName("+", "-")
/// Is equivalent to
/// anyOf(hasOverloadedOperatorName("+"), hasOverloadedOperatorName("-"))
extern const internal::VariadicFunction<
internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, std::vector<std::string>,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>,
StringRef, internal::hasAnyOverloadedOperatorNameFunc>
hasAnyOverloadedOperatorName;
/// Matches C++ classes that are directly or indirectly derived from a class
/// matching \c Base, or Objective-C classes that directly or indirectly
/// subclass a class matching \c Base.
@ -2776,6 +2858,46 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
}
/// Matches C++ classes that have a direct or indirect base matching \p
/// BaseSpecMatcher.
///
/// Example:
/// matcher hasAnyBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
/// \code
/// class Foo;
/// class Bar : Foo {};
/// class Baz : Bar {};
/// class SpecialBase;
/// class Proxy : SpecialBase {}; // matches Proxy
/// class IndirectlyDerived : Proxy {}; //matches IndirectlyDerived
/// \endcode
///
// FIXME: Refactor this and isDerivedFrom to reuse implementation.
AST_MATCHER_P(CXXRecordDecl, hasAnyBase, internal::Matcher<CXXBaseSpecifier>,
BaseSpecMatcher) {
return internal::matchesAnyBase(Node, BaseSpecMatcher, Finder, Builder);
}
/// Matches C++ classes that have a direct base matching \p BaseSpecMatcher.
///
/// Example:
/// matcher hasDirectBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
/// \code
/// class Foo;
/// class Bar : Foo {};
/// class Baz : Bar {};
/// class SpecialBase;
/// class Proxy : SpecialBase {}; // matches Proxy
/// class IndirectlyDerived : Proxy {}; // doesn't match
/// \endcode
AST_MATCHER_P(CXXRecordDecl, hasDirectBase, internal::Matcher<CXXBaseSpecifier>,
BaseSpecMatcher) {
return Node.hasDefinition() &&
llvm::any_of(Node.bases(), [&](const CXXBaseSpecifier &Base) {
return BaseSpecMatcher.matches(Base, Finder, Builder);
});
}
/// Similar to \c isDerivedFrom(), but also matches classes that directly
/// match \c Base.
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
@ -3269,11 +3391,9 @@ extern const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>,
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
AST_MATCHER_P(ObjCMessageExpr, matchesSelector, std::string, RegExp) {
assert(!RegExp.empty());
AST_MATCHER_REGEX(ObjCMessageExpr, matchesSelector, RegExp) {
std::string SelectorString = Node.getSelector().getAsString();
llvm::Regex RE(RegExp);
return RE.match(SelectorString);
return RegExp->match(SelectorString);
}
/// Matches when the selector is the empty selector
@ -3406,9 +3526,19 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
/// class Y { friend class X; };
/// \endcode
///
/// Usable as: Matcher<Expr>, Matcher<ValueDecl>
/// Example matches class Derived
/// (matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
/// \code
/// class Base {};
/// class Derived : Base {};
/// \endcode
///
/// Usable as: Matcher<Expr>, Matcher<FriendDecl>, Matcher<ValueDecl>,
/// Matcher<CXXBaseSpecifier>
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, ValueDecl),
hasType,
AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, ValueDecl,
CXXBaseSpecifier),
internal::Matcher<Decl>, InnerMatcher, 1) {
QualType QT = internal::getUnderlyingType(Node);
if (!QT.isNull())
@ -4194,6 +4324,34 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
return Matched;
}
/// Matches the ParmVarDecl nodes that are at the N'th position in the parameter
/// list. The parameter list could be that of either a block, function, or
/// objc-method.
///
///
/// Given
///
/// \code
/// void f(int a, int b, int c) {
/// }
/// \endcode
///
/// ``parmVarDecl(isAtPosition(0))`` matches ``int a``.
///
/// ``parmVarDecl(isAtPosition(1))`` matches ``int b``.
AST_MATCHER_P(ParmVarDecl, isAtPosition, unsigned, N) {
const clang::DeclContext *Context = Node.getParentFunctionOrMethod();
if (const auto *Decl = dyn_cast_or_null<FunctionDecl>(Context))
return N < Decl->param_size() && Decl->getParamDecl(N) == &Node;
if (const auto *Decl = dyn_cast_or_null<BlockDecl>(Context))
return N < Decl->param_size() && Decl->getParamDecl(N) == &Node;
if (const auto *Decl = dyn_cast_or_null<ObjCMethodDecl>(Context))
return N < Decl->param_size() && Decl->getParamDecl(N) == &Node;
return false;
}
/// Matches any parameter of a function or an ObjC method declaration or a
/// block.
///
@ -4532,7 +4690,7 @@ AST_POLYMORPHIC_MATCHER_P(equalsBoundNode,
// they're ever reused.
internal::NotEqualsBoundNodePredicate Predicate;
Predicate.ID = ID;
Predicate.Node = ast_type_traits::DynTypedNode::create(Node);
Predicate.Node = DynTypedNode::create(Node);
return Builder->removeBindings(Predicate);
}
@ -4716,6 +4874,19 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName,
return Name == Node.getOpcodeStr(Node.getOpcode());
}
/// Matches operator expressions (binary or unary) that have any of the
/// specified names.
///
/// hasAnyOperatorName("+", "-")
/// Is equivalent to
/// anyOf(hasOperatorName("+"), hasOperatorName("-"))
extern const internal::VariadicFunction<
internal::PolymorphicMatcherWithParam1<
internal::HasAnyOperatorNameMatcher, std::vector<std::string>,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, UnaryOperator)>,
StringRef, internal::hasAnyOperatorNameFunc>
hasAnyOperatorName;
/// Matches all kinds of assignment operators.
///
/// Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
@ -4728,7 +4899,7 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName,
/// (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
/// \code
/// struct S { S& operator=(const S&); };
/// void x() { S s1, s2; s1 = s2; })
/// void x() { S s1, s2; s1 = s2; }
/// \endcode
AST_POLYMORPHIC_MATCHER(isAssignmentOperator,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
@ -4736,6 +4907,26 @@ AST_POLYMORPHIC_MATCHER(isAssignmentOperator,
return Node.isAssignmentOp();
}
/// Matches comparison operators.
///
/// Example 1: matches a == b (matcher = binaryOperator(isComparisonOperator()))
/// \code
/// if (a == b)
/// a += b;
/// \endcode
///
/// Example 2: matches s1 < s2
/// (matcher = cxxOperatorCallExpr(isComparisonOperator()))
/// \code
/// struct S { bool operator<(const S& other); };
/// void x(S s1, S s2) { bool b1 = s1 < s2; }
/// \endcode
AST_POLYMORPHIC_MATCHER(isComparisonOperator,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
CXXOperatorCallExpr)) {
return Node.isComparisonOp();
}
/// Matches the left hand side of binary operator expressions.
///
/// Example matches a (matcher = binaryOperator(hasLHS()))
@ -4773,6 +4964,23 @@ inline internal::Matcher<BinaryOperator> hasEitherOperand(
return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher));
}
/// Matches if both matchers match with opposite sides of the binary operator.
///
/// Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
/// integerLiteral(equals(2)))
/// \code
/// 1 + 2 // Match
/// 2 + 1 // Match
/// 1 + 1 // No match
/// 2 + 2 // No match
/// \endcode
inline internal::Matcher<BinaryOperator>
hasOperands(const internal::Matcher<Expr> &Matcher1,
const internal::Matcher<Expr> &Matcher2) {
return anyOf(allOf(hasLHS(Matcher1), hasRHS(Matcher2)),
allOf(hasLHS(Matcher2), hasRHS(Matcher1)));
}
/// Matches if the operand of a unary operator matches.
///
/// Example matches true (matcher = hasUnaryOperand(
@ -4821,7 +5029,7 @@ AST_POLYMORPHIC_MATCHER_P(hasSourceExpression,
/// \endcode
///
/// If the matcher is use from clang-query, CastKind parameter
/// should be passed as a quoted string. e.g., ofKind("CK_NullToPointer").
/// should be passed as a quoted string. e.g., hasCastKind("CK_NullToPointer").
AST_MATCHER_P(CastExpr, hasCastKind, CastKind, Kind) {
return Node.getCastKind() == Kind;
}
@ -4845,42 +5053,58 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
return InnerMatcher.matches(Node.getType(), Finder, Builder);
}
/// Matches RecordDecl object that are spelled with "struct."
/// Matches TagDecl object that are spelled with "struct."
///
/// Example matches S, but not C or U.
/// Example matches S, but not C, U or E.
/// \code
/// struct S {};
/// class C {};
/// union U {};
/// enum E {};
/// \endcode
AST_MATCHER(RecordDecl, isStruct) {
AST_MATCHER(TagDecl, isStruct) {
return Node.isStruct();
}
/// Matches RecordDecl object that are spelled with "union."
/// Matches TagDecl object that are spelled with "union."
///
/// Example matches U, but not C or S.
/// Example matches U, but not C, S or E.
/// \code
/// struct S {};
/// class C {};
/// union U {};
/// enum E {};
/// \endcode
AST_MATCHER(RecordDecl, isUnion) {
AST_MATCHER(TagDecl, isUnion) {
return Node.isUnion();
}
/// Matches RecordDecl object that are spelled with "class."
/// Matches TagDecl object that are spelled with "class."
///
/// Example matches C, but not S or U.
/// Example matches C, but not S, U or E.
/// \code
/// struct S {};
/// class C {};
/// union U {};
/// enum E {};
/// \endcode
AST_MATCHER(RecordDecl, isClass) {
AST_MATCHER(TagDecl, isClass) {
return Node.isClass();
}
/// Matches TagDecl object that are spelled with "enum."
///
/// Example matches E, but not C, S or U.
/// \code
/// struct S {};
/// class C {};
/// union U {};
/// enum E {};
/// \endcode
AST_MATCHER(TagDecl, isEnum) {
return Node.isEnum();
}
/// Matches the true branch expression of a conditional operator.
///
/// Example 1 (conditional ternary operator): matches a
@ -5020,17 +5244,28 @@ AST_MATCHER_P(CXXMethodDecl, forEachOverridden,
return Matched;
}
/// Matches if the given method declaration is virtual.
/// Matches declarations of virtual methods and C++ base specifers that specify
/// virtual inheritance.
///
/// Given
/// Example:
/// \code
/// class A {
/// public:
/// virtual void x();
/// virtual void x(); // matches x
/// };
/// \endcode
/// matches A::x
AST_MATCHER(CXXMethodDecl, isVirtual) {
///
/// Example:
/// \code
/// class Base {};
/// class DirectlyDerived : virtual Base {}; // matches Base
/// class IndirectlyDerived : DirectlyDerived, Base {}; // matches Base
/// \endcode
///
/// Usable as: Matcher<CXXMethodDecl>, Matcher<CXXBaseSpecifier>
AST_POLYMORPHIC_MATCHER(isVirtual,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXMethodDecl,
CXXBaseSpecifier)) {
return Node.isVirtual();
}
@ -5982,6 +6217,21 @@ extern const AstTypeMatcher<EnumType> enumType;
extern const AstTypeMatcher<TemplateSpecializationType>
templateSpecializationType;
/// Matches C++17 deduced template specialization types, e.g. deduced class
/// template types.
///
/// Given
/// \code
/// template <typename T>
/// class C { public: C(T); };
///
/// C c(123);
/// \endcode
/// \c deducedTemplateSpecializationType() matches the type in the declaration
/// of the variable \c c.
extern const AstTypeMatcher<DeducedTemplateSpecializationType>
deducedTemplateSpecializationType;
/// Matches types nodes representing unary type transformations.
///
/// Given:
@ -6652,8 +6902,7 @@ AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>,
InnerMatcher) {
const auto &Parents = Finder->getASTContext().getParents(Node);
llvm::SmallVector<ast_type_traits::DynTypedNode, 8> Stack(Parents.begin(),
Parents.end());
llvm::SmallVector<DynTypedNode, 8> Stack(Parents.begin(), Parents.end());
while(!Stack.empty()) {
const auto &CurNode = Stack.back();
Stack.pop_back();
@ -6735,6 +6984,35 @@ AST_MATCHER(CXXNewExpr, isArray) {
return Node.isArray();
}
/// Matches placement new expression arguments.
///
/// Given:
/// \code
/// MyClass *p1 = new (Storage, 16) MyClass();
/// \endcode
/// cxxNewExpr(hasPlacementArg(1, integerLiteral(equals(16))))
/// matches the expression 'new (Storage, 16) MyClass()'.
AST_MATCHER_P2(CXXNewExpr, hasPlacementArg, unsigned, Index,
internal::Matcher<Expr>, InnerMatcher) {
return Node.getNumPlacementArgs() > Index &&
InnerMatcher.matches(*Node.getPlacementArg(Index), Finder, Builder);
}
/// Matches any placement new expression arguments.
///
/// Given:
/// \code
/// MyClass *p1 = new (Storage) MyClass();
/// \endcode
/// cxxNewExpr(hasAnyPlacementArg(anything()))
/// matches the expression 'new (Storage, 16) MyClass()'.
AST_MATCHER_P(CXXNewExpr, hasAnyPlacementArg, internal::Matcher<Expr>,
InnerMatcher) {
return llvm::any_of(Node.placement_arguments(), [&](const Expr *Arg) {
return InnerMatcher.matches(*Arg, Finder, Builder);
});
}
/// Matches array new expressions with a given array size.
///
/// Given:
@ -6865,19 +7143,6 @@ AST_MATCHER(OMPExecutableDirective, isStandaloneDirective) {
return Node.isStandaloneDirective();
}
/// Matches the Stmt AST node that is marked as being the structured-block
/// of an OpenMP executable directive.
///
/// Given
///
/// \code
/// #pragma omp parallel
/// {}
/// \endcode
///
/// ``stmt(isOMPStructuredBlock()))`` matches ``{}``.
AST_MATCHER(Stmt, isOMPStructuredBlock) { return Node.isOMPStructuredBlock(); }
/// Matches the structured-block of the OpenMP executable directive
///
/// Prerequisite: the executable directive must not be standalone directive.
@ -6925,10 +7190,12 @@ AST_MATCHER_P(OMPExecutableDirective, hasAnyClause,
/// \code
/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
/// #pragma omp parallel default(firstprivate)
/// #pragma omp parallel
/// \endcode
///
/// ``ompDefaultClause()`` matches ``default(none)`` and ``default(shared)``.
/// ``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and
/// ``default(firstprivate)``
extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause>
ompDefaultClause;
@ -6940,11 +7207,12 @@ extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause>
/// #pragma omp parallel
/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
/// #pragma omp parallel default(firstprivate)
/// \endcode
///
/// ``ompDefaultClause(isNoneKind())`` matches only ``default(none)``.
AST_MATCHER(OMPDefaultClause, isNoneKind) {
return Node.getDefaultKind() == OMPC_DEFAULT_none;
return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_none;
}
/// Matches if the OpenMP ``default`` clause has ``shared`` kind specified.
@ -6955,11 +7223,30 @@ AST_MATCHER(OMPDefaultClause, isNoneKind) {
/// #pragma omp parallel
/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
/// #pragma omp parallel default(firstprivate)
/// \endcode
///
/// ``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``.
AST_MATCHER(OMPDefaultClause, isSharedKind) {
return Node.getDefaultKind() == OMPC_DEFAULT_shared;
return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_shared;
}
/// Matches if the OpenMP ``default`` clause has ``firstprivate`` kind
/// specified.
///
/// Given
///
/// \code
/// #pragma omp parallel
/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
/// #pragma omp parallel default(firstprivate)
/// \endcode
///
/// ``ompDefaultClause(isFirstPrivateKind())`` matches only
/// ``default(firstprivate)``.
AST_MATCHER(OMPDefaultClause, isFirstPrivateKind) {
return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_firstprivate;
}
/// Matches if the OpenMP directive is allowed to contain the specified OpenMP
@ -6981,7 +7268,7 @@ AST_MATCHER(OMPDefaultClause, isSharedKind) {
/// ``isAllowedToContainClauseKind("OMPC_default").``
AST_MATCHER_P(OMPExecutableDirective, isAllowedToContainClauseKind,
OpenMPClauseKind, CKind) {
return isAllowedClauseForDirective(
return llvm::omp::isAllowedClauseForDirective(
Node.getDirectiveKind(), CKind,
Finder->getASTContext().getLangOpts().OpenMP);
}

View file

@ -40,7 +40,6 @@
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/NestedNameSpecifier.h"
@ -61,11 +60,13 @@
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Regex.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
@ -130,6 +131,9 @@ inline QualType getUnderlyingType(const FriendDecl &Node) {
return TSI->getType();
return QualType();
}
inline QualType getUnderlyingType(const CXXBaseSpecifier &Node) {
return Node.getType();
}
/// Unifies obtaining the FunctionProtoType pointer from both
/// FunctionProtoType and FunctionDecl nodes..
@ -142,14 +146,23 @@ inline const FunctionProtoType *getFunctionProtoType(const FunctionDecl &Node) {
return Node.getType()->getAs<FunctionProtoType>();
}
/// Unifies obtaining the access specifier from Decl and CXXBaseSpecifier nodes.
inline clang::AccessSpecifier getAccessSpecifier(const Decl &Node) {
return Node.getAccess();
}
inline clang::AccessSpecifier getAccessSpecifier(const CXXBaseSpecifier &Node) {
return Node.getAccessSpecifier();
}
/// Internal version of BoundNodes. Holds all the bound nodes.
class BoundNodesMap {
public:
/// Adds \c Node to the map with key \c ID.
///
/// The node's base type should be in NodeBaseType or it will be unaccessible.
void addNode(StringRef ID, const ast_type_traits::DynTypedNode& DynNode) {
NodeMap[ID] = DynNode;
void addNode(StringRef ID, const DynTypedNode &DynNode) {
NodeMap[std::string(ID)] = DynNode;
}
/// Returns the AST node bound to \c ID.
@ -165,10 +178,10 @@ public:
return It->second.get<T>();
}
ast_type_traits::DynTypedNode getNode(StringRef ID) const {
DynTypedNode getNode(StringRef ID) const {
IDToNodeMap::const_iterator It = NodeMap.find(ID);
if (It == NodeMap.end()) {
return ast_type_traits::DynTypedNode();
return DynTypedNode();
}
return It->second;
}
@ -183,8 +196,7 @@ public:
/// Note that we're using std::map here, as for memoization:
/// - we need a comparison operator
/// - we need an assignment operator
using IDToNodeMap =
std::map<std::string, ast_type_traits::DynTypedNode, std::less<>>;
using IDToNodeMap = std::map<std::string, DynTypedNode, std::less<>>;
const IDToNodeMap &getMap() const {
return NodeMap;
@ -223,7 +235,7 @@ public:
};
/// Add a binding from an id to a node.
void setBinding(StringRef Id, const ast_type_traits::DynTypedNode &DynNode) {
void setBinding(StringRef Id, const DynTypedNode &DynNode) {
if (Bindings.empty())
Bindings.emplace_back();
for (BoundNodesMap &Binding : Bindings)
@ -280,11 +292,10 @@ public:
///
/// May bind \p DynNode to an ID via \p Builder, or recurse into
/// the AST via \p Finder.
virtual bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
virtual bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const = 0;
virtual llvm::Optional<ast_type_traits::TraversalKind> TraversalKind() const {
virtual llvm::Optional<clang::TraversalKind> TraversalKind() const {
return llvm::None;
}
};
@ -307,8 +318,7 @@ public:
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const = 0;
bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return matches(DynNode.getUnchecked<T>(), Finder, Builder);
}
@ -347,7 +357,7 @@ public:
/// Takes ownership of the provided implementation pointer.
template <typename T>
DynTypedMatcher(MatcherInterface<T> *Implementation)
: SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()),
: SupportedKind(ASTNodeKind::getFromNodeKind<T>()),
RestrictKind(SupportedKind), Implementation(Implementation) {}
/// Construct from a variadic function.
@ -375,40 +385,44 @@ public:
};
static DynTypedMatcher
constructVariadic(VariadicOperator Op,
ast_type_traits::ASTNodeKind SupportedKind,
constructVariadic(VariadicOperator Op, ASTNodeKind SupportedKind,
std::vector<DynTypedMatcher> InnerMatchers);
static DynTypedMatcher
constructRestrictedWrapper(const DynTypedMatcher &InnerMatcher,
ast_type_traits::ASTNodeKind RestrictKind);
ASTNodeKind RestrictKind);
/// Get a "true" matcher for \p NodeKind.
///
/// It only checks that the node is of the right kind.
static DynTypedMatcher trueMatcher(ast_type_traits::ASTNodeKind NodeKind);
static DynTypedMatcher trueMatcher(ASTNodeKind NodeKind);
void setAllowBind(bool AB) { AllowBind = AB; }
/// Check whether this matcher could ever match a node of kind \p Kind.
/// \return \c false if this matcher will never match such a node. Otherwise,
/// return \c true.
bool canMatchNodesOfKind(ast_type_traits::ASTNodeKind Kind) const;
bool canMatchNodesOfKind(ASTNodeKind Kind) const;
/// Return a matcher that points to the same implementation, but
/// restricts the node types for \p Kind.
DynTypedMatcher dynCastTo(const ast_type_traits::ASTNodeKind Kind) const;
DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const;
/// Return a matcher that that points to the same implementation, but sets the
/// traversal kind.
///
/// If the traversal kind is already set, then \c TK overrides it.
DynTypedMatcher withTraversalKind(TraversalKind TK);
/// Returns true if the matcher matches the given \c DynNode.
bool matches(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const;
bool matches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const;
/// Same as matches(), but skips the kind check.
///
/// It is faster, but the caller must ensure the node is valid for the
/// kind of this matcher.
bool matchesNoKindCheck(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
bool matchesNoKindCheck(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const;
/// Bind the specified \p ID to the matcher.
@ -423,7 +437,7 @@ public:
/// include both in the ID to make it unique.
///
/// \c MatcherIDType supports operator< and provides strict weak ordering.
using MatcherIDType = std::pair<ast_type_traits::ASTNodeKind, uint64_t>;
using MatcherIDType = std::pair<ASTNodeKind, uint64_t>;
MatcherIDType getID() const {
/// FIXME: Document the requirements this imposes on matcher
/// implementations (no new() implementation_ during a Matches()).
@ -435,9 +449,7 @@ public:
///
/// \c matches() will always return false unless the node passed is of this
/// or a derived type.
ast_type_traits::ASTNodeKind getSupportedKind() const {
return SupportedKind;
}
ASTNodeKind getSupportedKind() const { return SupportedKind; }
/// Returns \c true if the passed \c DynTypedMatcher can be converted
/// to a \c Matcher<T>.
@ -445,9 +457,9 @@ public:
/// This method verifies that the underlying matcher in \c Other can process
/// nodes of types T.
template <typename T> bool canConvertTo() const {
return canConvertTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
return canConvertTo(ASTNodeKind::getFromNodeKind<T>());
}
bool canConvertTo(ast_type_traits::ASTNodeKind To) const;
bool canConvertTo(ASTNodeKind To) const;
/// Construct a \c Matcher<T> interface around the dynamic matcher.
///
@ -465,37 +477,31 @@ public:
/// If it is not compatible, then this matcher will never match anything.
template <typename T> Matcher<T> unconditionalConvertTo() const;
/// Returns the \c TraversalKind respected by calls to `match()`, if any.
///
/// Most matchers will not have a traversal kind set, instead relying on the
/// surrounding context. For those, \c llvm::None is returned.
llvm::Optional<clang::TraversalKind> getTraversalKind() const {
return Implementation->TraversalKind();
}
private:
DynTypedMatcher(ast_type_traits::ASTNodeKind SupportedKind,
ast_type_traits::ASTNodeKind RestrictKind,
IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
: SupportedKind(SupportedKind), RestrictKind(RestrictKind),
Implementation(std::move(Implementation)) {}
DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind,
IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
: SupportedKind(SupportedKind), RestrictKind(RestrictKind),
Implementation(std::move(Implementation)) {}
bool AllowBind = false;
ast_type_traits::ASTNodeKind SupportedKind;
ASTNodeKind SupportedKind;
/// A potentially stricter node kind.
///
/// It allows to perform implicit and dynamic cast of matchers without
/// needing to change \c Implementation.
ast_type_traits::ASTNodeKind RestrictKind;
ASTNodeKind RestrictKind;
IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
};
/// Wrapper base class for a wrapping matcher.
///
/// This is just a container for a DynTypedMatcher that can be used as a base
/// class for another matcher.
template <typename T>
class WrapperMatcherInterface : public MatcherInterface<T> {
protected:
explicit WrapperMatcherInterface(DynTypedMatcher &&InnerMatcher)
: InnerMatcher(std::move(InnerMatcher)) {}
const DynTypedMatcher InnerMatcher;
};
/// Wrapper of a MatcherInterface<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
@ -516,11 +522,11 @@ public:
/// Requires \c T to be derived from \c From.
template <typename From>
Matcher(const Matcher<From> &Other,
typename std::enable_if<std::is_base_of<From, T>::value &&
!std::is_same<From, T>::value>::type * = nullptr)
std::enable_if_t<std::is_base_of<From, T>::value &&
!std::is_same<From, T>::value> * = nullptr)
: Implementation(restrictMatcher(Other.Implementation)) {
assert(Implementation.getSupportedKind().isSame(
ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
ASTNodeKind::getFromNodeKind<T>()));
}
/// Implicitly converts \c Matcher<Type> to \c Matcher<QualType>.
@ -528,9 +534,8 @@ public:
/// The resulting matcher is not strict, i.e. ignores qualifiers.
template <typename TypeT>
Matcher(const Matcher<TypeT> &Other,
typename std::enable_if<
std::is_same<T, QualType>::value &&
std::is_same<TypeT, Type>::value>::type* = nullptr)
std::enable_if_t<std::is_same<T, QualType>::value &&
std::is_same<TypeT, Type>::value> * = nullptr)
: Implementation(new TypeToQualType<TypeT>(Other)) {}
/// Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the
@ -546,8 +551,7 @@ public:
bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
return Implementation.matches(ast_type_traits::DynTypedNode::create(Node),
Finder, Builder);
return Implementation.matches(DynTypedNode::create(Node), Finder, Builder);
}
/// Returns an ID that uniquely identifies the matcher.
@ -568,17 +572,19 @@ public:
/// does only matches in the absence of qualifiers, or not, i.e. simply
/// ignores any qualifiers.
template <typename TypeT>
class TypeToQualType : public WrapperMatcherInterface<QualType> {
class TypeToQualType : public MatcherInterface<QualType> {
const DynTypedMatcher InnerMatcher;
public:
TypeToQualType(const Matcher<TypeT> &InnerMatcher)
: TypeToQualType::WrapperMatcherInterface(InnerMatcher) {}
: InnerMatcher(InnerMatcher) {}
bool matches(const QualType &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (Node.isNull())
return false;
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
return this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder,
Builder);
}
};
@ -590,13 +596,13 @@ private:
friend class DynTypedMatcher;
static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) {
return Other.dynCastTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
return Other.dynCastTo(ASTNodeKind::getFromNodeKind<T>());
}
explicit Matcher(const DynTypedMatcher &Implementation)
: Implementation(restrictMatcher(Implementation)) {
assert(this->Implementation.getSupportedKind()
.isSame(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
assert(this->Implementation.getSupportedKind().isSame(
ASTNodeKind::getFromNodeKind<T>()));
}
DynTypedMatcher Implementation;
@ -616,9 +622,8 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
template <>
inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const {
assert(canConvertTo<QualType>());
const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind();
if (SourceKind.isSame(
ast_type_traits::ASTNodeKind::getFromNodeKind<Type>())) {
const ASTNodeKind SourceKind = getSupportedKind();
if (SourceKind.isSame(ASTNodeKind::getFromNodeKind<Type>())) {
// We support implicit conversion from Matcher<Type> to Matcher<QualType>
return unconditionalConvertTo<Type>();
}
@ -681,12 +686,12 @@ class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
std::is_base_of<FunctionDecl, T>::value,
"unsupported class for matcher");
static_assert(std::is_same<ArgT, StringRef>::value,
"argument type must be StringRef");
static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
"argument type must be std::vector<std::string>");
public:
explicit HasOverloadedOperatorNameMatcher(const StringRef Name)
: SingleNodeMatcherInterface<T>(), Name(Name) {}
explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names)
: SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
bool matchesNode(const T &Node) const override {
return matchesSpecialized(Node);
@ -698,17 +703,18 @@ private:
/// so this function returns true if the call is to an operator of the given
/// name.
bool matchesSpecialized(const CXXOperatorCallExpr &Node) const {
return getOperatorSpelling(Node.getOperator()) == Name;
return llvm::is_contained(Names, getOperatorSpelling(Node.getOperator()));
}
/// Returns true only if CXXMethodDecl represents an overloaded
/// operator and has the given operator name.
bool matchesSpecialized(const FunctionDecl &Node) const {
return Node.isOverloadedOperator() &&
getOperatorSpelling(Node.getOverloadedOperator()) == Name;
llvm::is_contained(
Names, getOperatorSpelling(Node.getOverloadedOperator()));
}
std::string Name;
const std::vector<std::string> Names;
};
/// Matches named declarations with a specific name.
@ -760,13 +766,15 @@ Matcher<ObjCMessageExpr> hasAnySelectorFunc(
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
/// not actually used.
template <typename T, typename DeclMatcherT>
class HasDeclarationMatcher : public WrapperMatcherInterface<T> {
class HasDeclarationMatcher : public MatcherInterface<T> {
static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
"instantiated with wrong types");
const DynTypedMatcher InnerMatcher;
public:
explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
: HasDeclarationMatcher::WrapperMatcherInterface(InnerMatcher) {}
: InnerMatcher(InnerMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
@ -920,9 +928,8 @@ private:
/// is \c NULL.
bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
return Node != nullptr &&
this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
return Node != nullptr && this->InnerMatcher.matches(
DynTypedNode::create(*Node), Finder, Builder);
}
};
@ -1004,8 +1011,8 @@ public:
template <typename T>
bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
ast_type_traits::TraversalKind Traverse, BindKind Bind) {
BoundNodesTreeBuilder *Builder, TraversalKind Traverse,
BindKind Bind) {
static_assert(std::is_base_of<Decl, T>::value ||
std::is_base_of<Stmt, T>::value ||
std::is_base_of<NestedNameSpecifier, T>::value ||
@ -1013,8 +1020,8 @@ public:
std::is_base_of<TypeLoc, T>::value ||
std::is_base_of<QualType, T>::value,
"unsupported type for recursive matching");
return matchesChildOf(ast_type_traits::DynTypedNode::create(Node),
getASTContext(), Matcher, Builder, Traverse, Bind);
return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher,
Builder, Traverse, Bind);
}
template <typename T>
@ -1029,8 +1036,8 @@ public:
std::is_base_of<TypeLoc, T>::value ||
std::is_base_of<QualType, T>::value,
"unsupported type for recursive matching");
return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node),
getASTContext(), Matcher, Builder, Bind);
return matchesDescendantOf(DynTypedNode::create(Node), getASTContext(),
Matcher, Builder, Bind);
}
// FIXME: Implement support for BindKind.
@ -1044,27 +1051,24 @@ public:
std::is_base_of<Stmt, T>::value ||
std::is_base_of<TypeLoc, T>::value,
"type not allowed for recursive matching");
return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node),
getASTContext(), Matcher, Builder, MatchMode);
return matchesAncestorOf(DynTypedNode::create(Node), getASTContext(),
Matcher, Builder, MatchMode);
}
virtual ASTContext &getASTContext() const = 0;
protected:
virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
ASTContext &Ctx, const DynTypedMatcher &Matcher,
virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
ast_type_traits::TraversalKind Traverse,
BindKind Bind) = 0;
TraversalKind Traverse, BindKind Bind) = 0;
virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
ASTContext &Ctx,
virtual bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx,
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
BindKind Bind) = 0;
virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
ASTContext &Ctx,
virtual bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx,
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
AncestorMatchMode MatchMode) = 0;
@ -1181,43 +1185,40 @@ struct ArgumentAdaptingMatcherFunc {
}
};
template <typename T>
class TraversalMatcher : public WrapperMatcherInterface<T> {
ast_type_traits::TraversalKind Traversal;
template <typename T> class TraversalMatcher : public MatcherInterface<T> {
const DynTypedMatcher InnerMatcher;
clang::TraversalKind Traversal;
public:
explicit TraversalMatcher(ast_type_traits::TraversalKind TK,
const Matcher<T> &ChildMatcher)
: TraversalMatcher::WrapperMatcherInterface(ChildMatcher), Traversal(TK) {
}
explicit TraversalMatcher(clang::TraversalKind TK,
const Matcher<T> &InnerMatcher)
: InnerMatcher(InnerMatcher), Traversal(TK) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(Node), Finder, Builder);
return this->InnerMatcher.matches(DynTypedNode::create(Node), Finder,
Builder);
}
llvm::Optional<ast_type_traits::TraversalKind>
TraversalKind() const override {
llvm::Optional<clang::TraversalKind> TraversalKind() const override {
return Traversal;
}
};
template <typename MatcherType> class TraversalWrapper {
public:
TraversalWrapper(ast_type_traits::TraversalKind TK,
const MatcherType &InnerMatcher)
TraversalWrapper(TraversalKind TK, const MatcherType &InnerMatcher)
: TK(TK), InnerMatcher(InnerMatcher) {}
template <typename T> operator Matcher<T>() const {
return internal::DynTypedMatcher::constructRestrictedWrapper(
new internal::TraversalMatcher<T>(TK, InnerMatcher),
ast_type_traits::ASTNodeKind::getFromNodeKind<T>())
ASTNodeKind::getFromNodeKind<T>())
.template unconditionalConvertTo<T>();
}
private:
ast_type_traits::TraversalKind TK;
TraversalKind TK;
MatcherType InnerMatcher;
};
@ -1300,8 +1301,7 @@ public:
template <typename T>
operator Matcher<T>() const {
return DynTypedMatcher::trueMatcher(
ast_type_traits::ASTNodeKind::getFromNodeKind<T>())
return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
.template unconditionalConvertTo<T>();
}
};
@ -1341,15 +1341,17 @@ public:
///
/// ChildT must be an AST base type.
template <typename T, typename ChildT>
class HasMatcher : public WrapperMatcherInterface<T> {
class HasMatcher : public MatcherInterface<T> {
const DynTypedMatcher InnerMatcher;
public:
explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
: HasMatcher::WrapperMatcherInterface(ChildMatcher) {}
explicit HasMatcher(const Matcher<ChildT> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesChildOf(Node, this->InnerMatcher, Builder,
ast_type_traits::TraversalKind::TK_AsIs,
TraversalKind::TK_AsIs,
ASTMatchFinder::BK_First);
}
};
@ -1360,19 +1362,21 @@ public:
/// As opposed to the HasMatcher, the ForEachMatcher will produce a match
/// for each child that matches.
template <typename T, typename ChildT>
class ForEachMatcher : public WrapperMatcherInterface<T> {
class ForEachMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<ChildT>::value,
"for each only accepts base type matcher");
public:
explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
: ForEachMatcher::WrapperMatcherInterface(ChildMatcher) {}
const DynTypedMatcher InnerMatcher;
bool matches(const T& Node, ASTMatchFinder* Finder,
BoundNodesTreeBuilder* Builder) const override {
public:
explicit ForEachMatcher(const Matcher<ChildT> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesChildOf(
Node, this->InnerMatcher, Builder,
ast_type_traits::TraversalKind::TK_IgnoreImplicitCastsAndParentheses,
TraversalKind::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_All);
}
};
@ -1393,7 +1397,7 @@ public:
template <typename T> operator Matcher<T>() const {
return DynTypedMatcher::constructVariadic(
Op, ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
Op, ASTNodeKind::getFromNodeKind<T>(),
getMatchers<T>(std::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
@ -1449,10 +1453,9 @@ BindableMatcher<T> makeAllOfComposite(
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
PI(InnerMatchers.end()));
return BindableMatcher<T>(
DynTypedMatcher::constructVariadic(
DynTypedMatcher::VO_AllOf,
ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
std::move(DynMatchers))
DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
ASTNodeKind::getFromNodeKind<T>(),
std::move(DynMatchers))
.template unconditionalConvertTo<T>());
}
@ -1474,17 +1477,19 @@ BindableMatcher<T> makeDynCastAllOfComposite(
///
/// DescendantT must be an AST base type.
template <typename T, typename DescendantT>
class HasDescendantMatcher : public WrapperMatcherInterface<T> {
class HasDescendantMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value,
"has descendant only accepts base type matcher");
const DynTypedMatcher DescendantMatcher;
public:
explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
: HasDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
: DescendantMatcher(DescendantMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
ASTMatchFinder::BK_First);
}
};
@ -1494,17 +1499,19 @@ public:
///
/// \c ParentT must be an AST base type.
template <typename T, typename ParentT>
class HasParentMatcher : public WrapperMatcherInterface<T> {
class HasParentMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<ParentT>::value,
"has parent only accepts base type matcher");
const DynTypedMatcher ParentMatcher;
public:
explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
: HasParentMatcher::WrapperMatcherInterface(ParentMatcher) {}
: ParentMatcher(ParentMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
return Finder->matchesAncestorOf(Node, this->ParentMatcher, Builder,
ASTMatchFinder::AMM_ParentOnly);
}
};
@ -1514,17 +1521,19 @@ public:
///
/// \c AncestorT must be an AST base type.
template <typename T, typename AncestorT>
class HasAncestorMatcher : public WrapperMatcherInterface<T> {
class HasAncestorMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<AncestorT>::value,
"has ancestor only accepts base type matcher");
const DynTypedMatcher AncestorMatcher;
public:
explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher)
: HasAncestorMatcher::WrapperMatcherInterface(AncestorMatcher) {}
: AncestorMatcher(AncestorMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
return Finder->matchesAncestorOf(Node, this->AncestorMatcher, Builder,
ASTMatchFinder::AMM_All);
}
};
@ -1536,18 +1545,20 @@ public:
/// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will match
/// for each descendant node that matches instead of only for the first.
template <typename T, typename DescendantT>
class ForEachDescendantMatcher : public WrapperMatcherInterface<T> {
class ForEachDescendantMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value,
"for each descendant only accepts base type matcher");
const DynTypedMatcher DescendantMatcher;
public:
explicit ForEachDescendantMatcher(
const Matcher<DescendantT> &DescendantMatcher)
: ForEachDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
: DescendantMatcher(DescendantMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
ASTMatchFinder::BK_All);
}
};
@ -1640,10 +1651,12 @@ public:
/// Matches nodes of type \c TLoc for which the inner
/// \c Matcher<T> matches.
template <typename TLoc, typename T>
class LocMatcher : public WrapperMatcherInterface<TLoc> {
class LocMatcher : public MatcherInterface<TLoc> {
const DynTypedMatcher InnerMatcher;
public:
explicit LocMatcher(const Matcher<T> &InnerMatcher)
: LocMatcher::WrapperMatcherInterface(InnerMatcher) {}
: InnerMatcher(InnerMatcher) {}
bool matches(const TLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
@ -1653,9 +1666,8 @@ public:
}
private:
static ast_type_traits::DynTypedNode
extract(const NestedNameSpecifierLoc &Loc) {
return ast_type_traits::DynTypedNode::create(*Loc.getNestedNameSpecifier());
static DynTypedNode extract(const NestedNameSpecifierLoc &Loc) {
return DynTypedNode::create(*Loc.getNestedNameSpecifier());
}
};
@ -1663,38 +1675,40 @@ private:
/// \c QualType.
///
/// Used to implement the \c loc() matcher.
class TypeLocTypeMatcher : public WrapperMatcherInterface<TypeLoc> {
class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> {
const DynTypedMatcher InnerMatcher;
public:
explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher)
: TypeLocTypeMatcher::WrapperMatcherInterface(InnerMatcher) {}
: InnerMatcher(InnerMatcher) {}
bool matches(const TypeLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (!Node)
return false;
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(Node.getType()), Finder, Builder);
return this->InnerMatcher.matches(DynTypedNode::create(Node.getType()),
Finder, Builder);
}
};
/// Matches nodes of type \c T for which the inner matcher matches on a
/// another node of type \c T that can be reached using a given traverse
/// function.
template <typename T>
class TypeTraverseMatcher : public WrapperMatcherInterface<T> {
template <typename T> class TypeTraverseMatcher : public MatcherInterface<T> {
const DynTypedMatcher InnerMatcher;
public:
explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher,
QualType (T::*TraverseFunction)() const)
: TypeTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
TraverseFunction(TraverseFunction) {}
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
QualType NextNode = (Node.*TraverseFunction)();
if (NextNode.isNull())
return false;
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
Builder);
}
private:
@ -1705,20 +1719,21 @@ private:
/// matcher matches on a another node of type \c T that can be reached using a
/// given traverse function.
template <typename T>
class TypeLocTraverseMatcher : public WrapperMatcherInterface<T> {
class TypeLocTraverseMatcher : public MatcherInterface<T> {
const DynTypedMatcher InnerMatcher;
public:
explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher,
TypeLoc (T::*TraverseFunction)() const)
: TypeLocTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
TraverseFunction(TraverseFunction) {}
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
TypeLoc NextNode = (Node.*TraverseFunction)();
if (!NextNode)
return false;
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
Builder);
}
private:
@ -1818,7 +1833,7 @@ struct NotEqualsBoundNodePredicate {
}
std::string ID;
ast_type_traits::DynTypedNode Node;
DynTypedNode Node;
};
template <typename Ty>
@ -1872,6 +1887,72 @@ CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) {
return Node.getSubStmt();
}
/// If \p Loc is (transitively) expanded from macro \p MacroName, returns the
/// location (in the chain of expansions) at which \p MacroName was
/// expanded. Since the macro may have been expanded inside a series of
/// expansions, that location may itself be a MacroID.
llvm::Optional<SourceLocation>
getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
const ASTContext &Context);
/// Matches overloaded operators with a specific name.
///
/// The type argument ArgT is not used by this matcher but is used by
/// PolymorphicMatcherWithParam1 and should be std::vector<std::string>>.
template <typename T, typename ArgT = std::vector<std::string>>
class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
static_assert(std::is_same<T, BinaryOperator>::value ||
std::is_same<T, UnaryOperator>::value,
"Matcher only supports `BinaryOperator` and `UnaryOperator`");
static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
"Matcher ArgT must be std::vector<std::string>");
public:
explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names)
: SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
bool matchesNode(const T &Node) const override {
StringRef OpName = getOpName(Node);
return llvm::any_of(
Names, [&](const std::string &Name) { return Name == OpName; });
}
private:
static StringRef getOpName(const UnaryOperator &Node) {
return Node.getOpcodeStr(Node.getOpcode());
}
static StringRef getOpName(const BinaryOperator &Node) {
return Node.getOpcodeStr();
}
const std::vector<std::string> Names;
};
using HasOpNameMatcher =
PolymorphicMatcherWithParam1<HasAnyOperatorNameMatcher,
std::vector<std::string>,
void(TypeList<BinaryOperator, UnaryOperator>)>;
HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs);
using HasOverloadOpNameMatcher = PolymorphicMatcherWithParam1<
HasOverloadedOperatorNameMatcher, std::vector<std::string>,
void(TypeList<CXXOperatorCallExpr, FunctionDecl>)>;
HasOverloadOpNameMatcher
hasAnyOverloadedOperatorNameFunc(ArrayRef<const StringRef *> NameRefs);
/// Returns true if \p Node has a base specifier matching \p BaseSpec.
///
/// A class is not considered to be derived from itself.
bool matchesAnyBase(const CXXRecordDecl &Node,
const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder);
std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex,
llvm::Regex::RegexFlags Flags,
StringRef MatcherID);
} // namespace internal
} // namespace ast_matchers

View file

@ -134,9 +134,8 @@
class matcher_##DefineMatcher##OverloadId##Matcher \
: public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
ParamType const &A##Param) \
: Param(A##Param) {} \
explicit matcher_##DefineMatcher##OverloadId##Matcher(ParamType A##Param) \
: Param(std::move(A##Param)) {} \
bool matches(const Type &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
@ -147,12 +146,13 @@
}; \
} \
inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
ParamType const &Param) { \
ParamType Param) { \
return ::clang::ast_matchers::internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \
new internal::matcher_##DefineMatcher##OverloadId##Matcher( \
std::move(Param))); \
} \
typedef ::clang::ast_matchers::internal::Matcher<Type>( \
&DefineMatcher##_Type##OverloadId)(ParamType const &Param); \
typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
&DefineMatcher##_Type##OverloadId)(ParamType Param); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
@ -183,9 +183,9 @@
class matcher_##DefineMatcher##OverloadId##Matcher \
: public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
public: \
matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
ParamType2 const &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) {} \
matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 A##Param1, \
ParamType2 A##Param2) \
: Param1(std::move(A##Param1)), Param2(std::move(A##Param2)) {} \
bool matches(const Type &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
@ -197,14 +197,14 @@
}; \
} \
inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
ParamType1 const &Param1, ParamType2 const &Param2) { \
ParamType1 Param1, ParamType2 Param2) { \
return ::clang::ast_matchers::internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \
Param2)); \
new internal::matcher_##DefineMatcher##OverloadId##Matcher( \
std::move(Param1), std::move(Param2))); \
} \
typedef ::clang::ast_matchers::internal::Matcher<Type>( \
&DefineMatcher##_Type##OverloadId)(ParamType1 const &Param1, \
ParamType2 const &Param2); \
typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
&DefineMatcher##_Type##OverloadId)(ParamType1 Param1, \
ParamType2 Param2); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
@ -272,9 +272,8 @@
class matcher_##DefineMatcher##OverloadId##Matcher \
: public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
ParamType const &A##Param) \
: Param(A##Param) {} \
explicit matcher_##DefineMatcher##OverloadId##Matcher(ParamType A##Param) \
: Param(std::move(A##Param)) {} \
bool matches(const NodeType &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
@ -287,15 +286,14 @@
inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
ReturnTypesF> \
DefineMatcher(ParamType const &Param) { \
DefineMatcher(ParamType Param) { \
return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
ReturnTypesF>(Param); \
ReturnTypesF>(std::move(Param)); \
} \
typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
ParamType const &Param); \
ReturnTypesF> (&DefineMatcher##_Type##OverloadId)(ParamType Param); \
template <typename NodeType, typename ParamT> \
bool internal:: \
matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \
@ -325,9 +323,9 @@
class matcher_##DefineMatcher##OverloadId##Matcher \
: public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
public: \
matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
ParamType2 const &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) {} \
matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 A##Param1, \
ParamType2 A##Param2) \
: Param1(std::move(A##Param1)), Param2(std::move(A##Param2)) {} \
bool matches(const NodeType &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
@ -341,15 +339,15 @@
inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
ParamType2, ReturnTypesF> \
DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) { \
DefineMatcher(ParamType1 Param1, ParamType2 Param2) { \
return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
ParamType2, ReturnTypesF>(Param1, Param2); \
ParamType2, ReturnTypesF>(std::move(Param1), std::move(Param2)); \
} \
typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
ParamType1 const &Param1, ParamType2 const &Param2); \
ParamType2, ReturnTypesF> (&DefineMatcher##_Type##OverloadId)( \
ParamType1 Param1, ParamType2 Param2); \
template <typename NodeType, typename ParamT1, typename ParamT2> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType, ParamT1, ParamT2>:: \
@ -440,4 +438,122 @@
ReturnTypesF>::Func MatcherName##Loc; \
AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
/// AST_MATCHER_REGEX(Type, DefineMatcher, Param) { ... }
/// defines a function named DefineMatcher() that takes a regular expression
/// string paramater and an optional RegexFlags parameter and returns a
/// Matcher<Type> object.
///
/// The code between the curly braces has access to the following variables:
///
/// Node: the AST node being matched; its type is Type.
/// Param: a pointer to an \ref llvm::Regex object
/// Finder: an ASTMatchFinder*.
/// Builder: a BoundNodesTreeBuilder*.
///
/// The code should return true if 'Node' matches.
#define AST_MATCHER_REGEX(Type, DefineMatcher, Param) \
AST_MATCHER_REGEX_OVERLOAD(Type, DefineMatcher, Param, 0)
#define AST_MATCHER_REGEX_OVERLOAD(Type, DefineMatcher, Param, OverloadId) \
namespace internal { \
class matcher_##DefineMatcher##OverloadId##Matcher \
: public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
std::shared_ptr<llvm::Regex> RE) \
: Param(std::move(RE)) {} \
bool matches(const Type &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
*Builder) const override; \
\
private: \
std::shared_ptr<llvm::Regex> const Param; \
}; \
} \
inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
llvm::StringRef Param, llvm::Regex::RegexFlags RegexFlags) { \
return ::clang::ast_matchers::internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher( \
::clang::ast_matchers::internal::createAndVerifyRegex( \
Param, RegexFlags, #DefineMatcher))); \
} \
inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
llvm::StringRef Param) { \
return DefineMatcher(Param, llvm::Regex::NoFlags); \
} \
\
typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
&DefineMatcher##_Type##OverloadId##Flags)(llvm::StringRef, \
llvm::Regex::RegexFlags); \
typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
&DefineMatcher##_Type##OverloadId)(llvm::StringRef); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
/// AST_POLYMORPHIC_MATCHER_REGEX(DefineMatcher, ReturnTypesF, Param) { ... }
/// defines a function named DefineMatcher() that takes a regular expression
/// string paramater and an optional RegexFlags parameter that is polymorphic in
/// the return type.
///
/// The variables are the same as for
/// AST_MATCHER_REGEX, with the addition of NodeType, which specifies the node
/// type of the matcher Matcher<NodeType> returned by the function matcher().
#define AST_POLYMORPHIC_MATCHER_REGEX(DefineMatcher, ReturnTypesF, Param) \
AST_POLYMORPHIC_MATCHER_REGEX_OVERLOAD(DefineMatcher, ReturnTypesF, Param, 0)
#define AST_POLYMORPHIC_MATCHER_REGEX_OVERLOAD(DefineMatcher, ReturnTypesF, \
Param, OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT> \
class matcher_##DefineMatcher##OverloadId##Matcher \
: public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
std::shared_ptr<llvm::Regex> RE) \
: Param(std::move(RE)) {} \
bool matches(const NodeType &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
*Builder) const override; \
\
private: \
std::shared_ptr<llvm::Regex> const Param; \
}; \
} \
inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, \
std::shared_ptr<llvm::Regex>, ReturnTypesF> \
DefineMatcher(llvm::StringRef Param, llvm::Regex::RegexFlags RegexFlags) { \
return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, \
std::shared_ptr<llvm::Regex>, ReturnTypesF>( \
::clang::ast_matchers::internal::createAndVerifyRegex( \
Param, RegexFlags, #DefineMatcher)); \
} \
inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, \
std::shared_ptr<llvm::Regex>, ReturnTypesF> \
DefineMatcher(llvm::StringRef Param) { \
return DefineMatcher(Param, llvm::Regex::NoFlags); \
} \
typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, \
std::shared_ptr<llvm::Regex>, ReturnTypesF> ( \
&DefineMatcher##_Type##OverloadId##Flags)( \
llvm::StringRef Param, llvm::Regex::RegexFlags RegexFlags); \
typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, \
std::shared_ptr<llvm::Regex>, ReturnTypesF> ( \
&DefineMatcher##_Type##OverloadId)(llvm::StringRef Param); \
template <typename NodeType, typename ParamT> \
bool internal:: \
matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \
const NodeType &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
const
#endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H

View file

@ -65,6 +65,7 @@ public:
ET_RegistryNotBindable = 4,
ET_RegistryAmbiguousOverload = 5,
ET_RegistryValueNotFound = 6,
ET_RegistryUnknownEnumWithReplace = 7,
ET_ParserStringError = 100,
ET_ParserNoOpenParen = 101,

View file

@ -1,4 +1,5 @@
//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
//===--- VariantValue.h - Polymorphic value type ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@ -43,11 +44,10 @@ class ArgKind {
ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
/// Constructor for matcher types.
ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
: K(AK_Matcher), MatcherKind(MatcherKind) {}
ArgKind(ASTNodeKind MatcherKind) : K(AK_Matcher), MatcherKind(MatcherKind) {}
Kind getArgKind() const { return K; }
ast_type_traits::ASTNodeKind getMatcherKind() const {
ASTNodeKind getMatcherKind() const {
assert(K == AK_Matcher);
return MatcherKind;
}
@ -71,7 +71,7 @@ class ArgKind {
private:
Kind K;
ast_type_traits::ASTNodeKind MatcherKind;
ASTNodeKind MatcherKind;
};
using ast_matchers::internal::DynTypedMatcher;
@ -93,7 +93,7 @@ class VariantMatcher {
/// Methods that depend on T from hasTypedMatcher/getTypedMatcher.
class MatcherOps {
public:
MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
MatcherOps(ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
bool canConstructFrom(const DynTypedMatcher &Matcher,
bool &IsExactMatch) const;
@ -114,7 +114,7 @@ class VariantMatcher {
~MatcherOps() = default;
private:
ast_type_traits::ASTNodeKind NodeKind;
ASTNodeKind NodeKind;
};
/// Payload interface to be specialized by each matcher type.
@ -127,7 +127,7 @@ class VariantMatcher {
virtual std::string getTypeAsString() const = 0;
virtual llvm::Optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps &Ops) const = 0;
virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
virtual bool isConvertibleTo(ASTNodeKind Kind,
unsigned *Specificity) const = 0;
};
@ -184,8 +184,7 @@ public:
///
/// \param Specificity value corresponding to the "specificity" of the
/// conversion.
bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
unsigned *Specificity) const {
bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const {
if (Value)
return Value->isConvertibleTo(Kind, Specificity);
return false;
@ -223,8 +222,7 @@ private:
template <typename T>
struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
TypedMatcherOps()
: MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {}
TypedMatcherOps() : MatcherOps(ASTNodeKind::getFromNodeKind<T>()) {}
typedef ast_matchers::internal::Matcher<T> MatcherT;
DynTypedMatcher

View file

@ -0,0 +1,45 @@
//===- GtestMatchers.h - AST Matchers for GTest -----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements matchers specific to structures in the Googletest
// (gtest) framework.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ASTMATCHERS_GTESTMATCHERS_H
#define LLVM_CLANG_ASTMATCHERS_GTESTMATCHERS_H
#include "clang/AST/Stmt.h"
#include "clang/ASTMatchers/ASTMatchers.h"
namespace clang {
namespace ast_matchers {
/// Gtest's comparison operations.
enum class GtestCmp {
Eq,
Ne,
Ge,
Gt,
Le,
Lt,
};
/// Matcher for gtest's ASSERT_... macros.
internal::BindableMatcher<Stmt> gtestAssert(GtestCmp Cmp, StatementMatcher Left,
StatementMatcher Right);
/// Matcher for gtest's EXPECT_... macros.
internal::BindableMatcher<Stmt> gtestExpect(GtestCmp Cmp, StatementMatcher Left,
StatementMatcher Right);
} // namespace ast_matchers
} // namespace clang
#endif // LLVM_CLANG_ASTMATCHERS_GTESTMATCHERS_H

View file

@ -167,9 +167,7 @@ public:
}
/// Releases the memory held by the dominator tree.
virtual void releaseMemory() {
DT.releaseMemory();
}
virtual void releaseMemory() { DT.reset(); }
/// Converts the dominator tree to human readable form.
virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const {
@ -351,7 +349,7 @@ ClangCFGPostDomReverseChildrenGetter::Get(
///
template <> struct GraphTraits<clang::DomTreeNode *> {
using NodeRef = ::clang::DomTreeNode *;
using ChildIteratorType = ::clang::DomTreeNode::iterator;
using ChildIteratorType = ::clang::DomTreeNode::const_iterator;
static NodeRef getEntryNode(NodeRef N) { return N; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }

View file

@ -70,8 +70,8 @@ public:
~LiveVariables() override;
/// Compute the liveness information for a given CFG.
static LiveVariables *computeLiveness(AnalysisDeclContext &analysisContext,
bool killAtAssign);
static std::unique_ptr<LiveVariables>
computeLiveness(AnalysisDeclContext &analysisContext, bool killAtAssign);
/// Return true if a variable is live at the end of a
/// specified block.
@ -97,7 +97,8 @@ public:
void runOnAllBlocks(Observer &obs);
static LiveVariables *create(AnalysisDeclContext &analysisContext) {
static std::unique_ptr<LiveVariables>
create(AnalysisDeclContext &analysisContext) {
return computeLiveness(analysisContext, true);
}
@ -110,7 +111,8 @@ private:
class RelaxedLiveVariables : public LiveVariables {
public:
static LiveVariables *create(AnalysisDeclContext &analysisContext) {
static std::unique_ptr<LiveVariables>
create(AnalysisDeclContext &analysisContext) {
return computeLiveness(analysisContext, false);
}

View file

@ -108,7 +108,8 @@ public:
// Used by AnalyisContext to construct this object.
static const void *getTag();
static PostOrderCFGView *create(AnalysisDeclContext &analysisContext);
static std::unique_ptr<PostOrderCFGView>
create(AnalysisDeclContext &analysisContext);
};
} // namespace clang

View file

@ -108,8 +108,10 @@ public:
/// \param LockName -- A StringRef name for the lock expression, to be printed
/// in the error message.
/// \param Loc -- The SourceLocation of the Unlock
/// \param LocPreviousUnlock -- If valid, the location of a previous Unlock.
virtual void handleUnmatchedUnlock(StringRef Kind, Name LockName,
SourceLocation Loc) {}
SourceLocation Loc,
SourceLocation LocPreviousUnlock) {}
/// Warn about an unlock function call that attempts to unlock a lock with
/// the incorrect lock kind. For instance, a shared lock being unlocked

View file

@ -110,6 +110,10 @@ public:
virtual void handleUseOfUninitVariable(const VarDecl *vd,
const UninitUse &use) {}
/// Called when the uninitialized variable is used as const refernce argument.
virtual void handleConstRefUseOfUninitVariable(const VarDecl *vd,
const UninitUse &use) {}
/// Called when the uninitialized variable analysis detects the
/// idiom 'int x = x'. All other uses of 'x' within the initializer
/// are handled by handleUseOfUninitVariable.

View file

@ -1,4 +1,4 @@
// AnalysisDeclContext.h - Analysis context for Path Sens analysis -*- C++ -*-//
//===- AnalysisDeclContext.h - Context for path sensitivity -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,8 +6,11 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines AnalysisDeclContext, a class that manages the analysis
// context data for path sensitive analysis.
/// \file
/// This file defines AnalysisDeclContext, a class that manages the analysis
/// context data for context sensitive and path sensitive analysis.
/// It also defines the helper classes to model entering, leaving or inlining
/// function calls.
//
//===----------------------------------------------------------------------===//
@ -64,14 +67,14 @@ public:
// which creates the analysis object given an AnalysisDeclContext.
};
/// AnalysisDeclContext contains the context data for the function or method
/// under analysis.
/// AnalysisDeclContext contains the context data for the function, method
/// or block under analysis.
class AnalysisDeclContext {
/// Backpoint to the AnalysisManager object that created this
/// AnalysisDeclContext. This may be null.
AnalysisDeclContextManager *Manager;
// Backpoint to the AnalysisManager object that created this
// AnalysisDeclContext. This may be null.
AnalysisDeclContextManager *ADCMgr;
const Decl * const D;
const Decl *const D;
std::unique_ptr<CFG> cfg, completeCFG;
std::unique_ptr<CFGStmtMap> cfgStmtMap;
@ -86,45 +89,36 @@ class AnalysisDeclContext {
llvm::BumpPtrAllocator A;
llvm::DenseMap<const BlockDecl *,void *> *ReferencedBlockVars = nullptr;
llvm::DenseMap<const BlockDecl *, void *> *ReferencedBlockVars = nullptr;
void *ManagedAnalyses = nullptr;
public:
AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
const Decl *D);
AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D);
AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
const Decl *D,
const CFG::BuildOptions &BuildOptions);
AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D,
const CFG::BuildOptions &BuildOptions);
~AnalysisDeclContext();
ASTContext &getASTContext() const { return D->getASTContext(); }
const Decl *getDecl() const { return D; }
/// Return the AnalysisDeclContextManager (if any) that created
/// this AnalysisDeclContext.
AnalysisDeclContextManager *getManager() const {
return Manager;
}
AnalysisDeclContextManager *getManager() const { return ADCMgr; }
/// Return the build options used to construct the CFG.
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
}
CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
const CFG::BuildOptions &getCFGBuildOptions() const {
return cfgBuildOptions;
}
/// getAddEHEdges - Return true iff we are adding exceptional edges from
/// callExprs. If this is false, then try/catch statements and blocks
/// reachable from them can appear to be dead in the CFG, analysis passes must
/// cope with that.
/// \returns Whether we are adding exception handling edges from CallExprs.
/// If this is false, then try/catch statements and blocks reachable from them
/// can appear to be dead in the CFG, analysis passes must cope with that.
bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
bool getUseUnoptimizedCFG() const {
return !cfgBuildOptions.PruneTriviallyFalseEdges;
return !cfgBuildOptions.PruneTriviallyFalseEdges;
}
bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
@ -132,25 +126,25 @@ public:
void registerForcedBlockExpression(const Stmt *stmt);
const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
/// Get the body of the Declaration.
/// \returns The body of the stored Decl \c D.
Stmt *getBody() const;
/// Get the body of the Declaration.
/// \copydoc AnalysisDeclContext::getBody()
/// \param[out] IsAutosynthesized Specifies if the body is auto-generated
/// by the BodyFarm.
Stmt *getBody(bool &IsAutosynthesized) const;
/// Checks if the body of the Decl is generated by the BodyFarm.
/// \returns Whether the body of the Decl \c D is generated by the BodyFarm.
///
/// Note, the lookup is not free. We are going to call getBody behind
/// \note The lookup is not free. We are going to call getBody behind
/// the scenes.
/// \sa getBody
bool isBodyAutosynthesized() const;
/// Checks if the body of the Decl is generated by the BodyFarm from a
/// model file.
/// \returns Whether the body of the Decl \c D is generated by the BodyFarm
/// from a model file.
///
/// Note, the lookup is not free. We are going to call getBody behind
/// \note The lookup is not free. We are going to call getBody behind
/// the scenes.
/// \sa getBody
bool isBodyAutosynthesizedFromModelFile() const;
@ -161,61 +155,64 @@ public:
CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
/// Return a version of the CFG without any edges pruned.
/// \returns A version of the CFG without any edges pruned.
CFG *getUnoptimizedCFG();
void dumpCFG(bool ShowColors);
/// Returns true if we have built a CFG for this analysis context.
/// Note that this doesn't correspond to whether or not a valid CFG exists, it
/// \returns Whether we have built a CFG for this analysis context.
///
/// \note This doesn't correspond to whether or not a valid CFG exists, it
/// corresponds to whether we *attempted* to build one.
bool isCFGBuilt() const { return builtCFG; }
ParentMap &getParentMap();
using referenced_decls_iterator = const VarDecl * const *;
using referenced_decls_iterator = const VarDecl *const *;
llvm::iterator_range<referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl *BD);
/// Return the ImplicitParamDecl* associated with 'self' if this
/// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise.
/// \returns The ImplicitParamDecl associated with \c self if this
/// AnalysisDeclContext wraps an ObjCMethodDecl or nullptr otherwise.
const ImplicitParamDecl *getSelfDecl() const;
const StackFrameContext *getStackFrame(LocationContext const *Parent,
/// \copydoc LocationContextManager::getStackFrame()
const StackFrameContext *getStackFrame(LocationContext const *ParentLC,
const Stmt *S, const CFGBlock *Blk,
unsigned BlockCount, unsigned Idx);
unsigned BlockCount, unsigned Index);
/// \copydoc LocationContextManager::getBlockInvocationContext()
const BlockInvocationContext *
getBlockInvocationContext(const LocationContext *parent,
const BlockDecl *BD,
const void *ContextData);
getBlockInvocationContext(const LocationContext *ParentLC,
const BlockDecl *BD, const void *Data);
/// Return the specified analysis object, lazily running the analysis if
/// necessary. Return NULL if the analysis could not run.
template <typename T>
T *getAnalysis() {
/// \returns The specified analysis object, lazily running the analysis if
/// necessary or nullptr if the analysis could not run.
template <typename T> T *getAnalysis() {
const void *tag = T::getTag();
ManagedAnalysis *&data = getAnalysisImpl(tag);
if (!data) {
std::unique_ptr<ManagedAnalysis> &data = getAnalysisImpl(tag);
if (!data)
data = T::create(*this);
}
return static_cast<T *>(data);
return static_cast<T *>(data.get());
}
/// Returns true if the root namespace of the given declaration is the 'std'
/// C++ namespace.
/// \returns Whether the root namespace of \p D is the \c std C++ namespace.
static bool isInStdNamespace(const Decl *D);
private:
ManagedAnalysis *&getAnalysisImpl(const void* tag);
std::unique_ptr<ManagedAnalysis> &getAnalysisImpl(const void *tag);
LocationContextManager &getLocationContextManager();
};
/// It wraps the AnalysisDeclContext to represent both the call stack with
/// the help of StackFrameContext and inside the function calls the
/// BlockInvocationContext. It is needed for context sensitive analysis to
/// model entering, leaving or inlining function calls.
class LocationContext : public llvm::FoldingSetNode {
public:
enum ContextKind { StackFrame, Scope, Block };
enum ContextKind { StackFrame, Block };
private:
ContextKind Kind;
@ -229,8 +226,7 @@ private:
protected:
LocationContext(ContextKind k, AnalysisDeclContext *ctx,
const LocationContext *parent,
int64_t ID)
const LocationContext *parent, int64_t ID)
: Kind(k), Ctx(ctx), Parent(parent), ID(ID) {}
public:
@ -238,9 +234,7 @@ public:
ContextKind getKind() const { return Kind; }
int64_t getID() const {
return ID;
}
int64_t getID() const { return ID; }
AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
@ -248,58 +242,61 @@ public:
bool isParentOf(const LocationContext *LC) const;
const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
const Decl *getDecl() const { return Ctx->getDecl(); }
CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
CFG *getCFG() const { return Ctx->getCFG(); }
template <typename T>
T *getAnalysis() const {
return getAnalysisDeclContext()->getAnalysis<T>();
}
template <typename T> T *getAnalysis() const { return Ctx->getAnalysis<T>(); }
const ParentMap &getParentMap() const {
return getAnalysisDeclContext()->getParentMap();
}
const ParentMap &getParentMap() const { return Ctx->getParentMap(); }
const ImplicitParamDecl *getSelfDecl() const {
return Ctx->getSelfDecl();
}
/// \copydoc AnalysisDeclContext::getSelfDecl()
const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); }
const StackFrameContext *getStackFrame() const;
/// Return true if the current LocationContext has no caller context.
/// \returns Whether the current LocationContext has no caller context.
virtual bool inTopFrame() const;
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
void dumpStack(
raw_ostream &Out, const char *NL = "\n",
std::function<void(const LocationContext *)> printMoreInfoPerContext =
[](const LocationContext *) {}) const;
/// Prints out the call stack.
///
/// \param Out The out stream.
LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const;
/// Prints out the call stack in \c json format.
///
/// \param Out The out stream.
/// \param NL The newline.
/// \param Space The space count for indentation.
/// \param IsDot Whether the output format is \c dot.
/// \param printMoreInfoPerContext
/// A callback to print more information for each context, for example:
/// \code
/// [&](const LocationContext *LC) { LC->dump(); }
/// \endcode
void printJson(
raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
bool IsDot = false,
std::function<void(const LocationContext *)> printMoreInfoPerContext =
[](const LocationContext *) {}) const;
void dump() const;
LLVM_DUMP_METHOD void dump() const;
public:
static void ProfileCommon(llvm::FoldingSetNodeID &ID,
ContextKind ck,
static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck,
AnalysisDeclContext *ctx,
const LocationContext *parent,
const void *data);
const LocationContext *parent, const void *data);
};
/// It represents a stack frame of the call stack (based on CallEvent).
class StackFrameContext : public LocationContext {
friend class LocationContextManager;
// The callsite where this stack frame is established.
// The call site where this stack frame is established.
const Stmt *CallSite;
// The parent block of the callsite.
// The parent block of the call site.
const CFGBlock *Block;
// The number of times the 'Block' has been visited.
@ -307,14 +304,14 @@ class StackFrameContext : public LocationContext {
// called multiple times in a loop.
const unsigned BlockCount;
// The index of the callsite in the CFGBlock.
// The index of the call site in the CFGBlock.
const unsigned Index;
StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
const Stmt *s, const CFGBlock *blk, unsigned blockCount,
unsigned idx, int64_t ID)
: LocationContext(StackFrame, ctx, parent, ID), CallSite(s), Block(blk),
BlockCount(blockCount), Index(idx) {}
StackFrameContext(AnalysisDeclContext *ADC, const LocationContext *ParentLC,
const Stmt *S, const CFGBlock *Block, unsigned BlockCount,
unsigned Index, int64_t ID)
: LocationContext(StackFrame, ADC, ParentLC, ID), CallSite(S),
Block(Block), BlockCount(BlockCount), Index(Index) {}
public:
~StackFrameContext() override = default;
@ -323,117 +320,100 @@ public:
const CFGBlock *getCallSiteBlock() const { return Block; }
/// Return true if the current LocationContext has no caller context.
bool inTopFrame() const override { return getParent() == nullptr; }
bool inTopFrame() const override { return getParent() == nullptr; }
unsigned getIndex() const { return Index; }
CFGElement getCallSiteCFGElement() const { return (*Block)[Index]; }
void Profile(llvm::FoldingSetNodeID &ID) override;
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
const LocationContext *parent, const Stmt *s,
const CFGBlock *blk, unsigned blockCount, unsigned idx) {
ProfileCommon(ID, StackFrame, ctx, parent, s);
ID.AddPointer(blk);
ID.AddInteger(blockCount);
ID.AddInteger(idx);
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
const LocationContext *ParentLC, const Stmt *S,
const CFGBlock *Block, unsigned BlockCount,
unsigned Index) {
ProfileCommon(ID, StackFrame, ADC, ParentLC, S);
ID.AddPointer(Block);
ID.AddInteger(BlockCount);
ID.AddInteger(Index);
}
static bool classof(const LocationContext *Ctx) {
return Ctx->getKind() == StackFrame;
}
};
class ScopeContext : public LocationContext {
friend class LocationContextManager;
const Stmt *Enter;
ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
const Stmt *s, int64_t ID)
: LocationContext(Scope, ctx, parent, ID), Enter(s) {}
public:
~ScopeContext() override = default;
void Profile(llvm::FoldingSetNodeID &ID) override;
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
const LocationContext *parent, const Stmt *s) {
ProfileCommon(ID, Scope, ctx, parent, s);
}
static bool classof(const LocationContext *Ctx) {
return Ctx->getKind() == Scope;
static bool classof(const LocationContext *LC) {
return LC->getKind() == StackFrame;
}
};
/// It represents a block invocation (based on BlockCall).
class BlockInvocationContext : public LocationContext {
friend class LocationContextManager;
const BlockDecl *BD;
// FIXME: Come up with a more type-safe way to model context-sensitivity.
const void *ContextData;
const void *Data;
BlockInvocationContext(AnalysisDeclContext *ctx,
const LocationContext *parent, const BlockDecl *bd,
const void *contextData, int64_t ID)
: LocationContext(Block, ctx, parent, ID), BD(bd),
ContextData(contextData) {}
BlockInvocationContext(AnalysisDeclContext *ADC,
const LocationContext *ParentLC, const BlockDecl *BD,
const void *Data, int64_t ID)
: LocationContext(Block, ADC, ParentLC, ID), BD(BD), Data(Data) {}
public:
~BlockInvocationContext() override = default;
const BlockDecl *getBlockDecl() const { return BD; }
const void *getContextData() const { return ContextData; }
const void *getData() const { return Data; }
void Profile(llvm::FoldingSetNodeID &ID) override;
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
const LocationContext *parent, const BlockDecl *bd,
const void *contextData) {
ProfileCommon(ID, Block, ctx, parent, bd);
ID.AddPointer(contextData);
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
const LocationContext *ParentLC, const BlockDecl *BD,
const void *Data) {
ProfileCommon(ID, Block, ADC, ParentLC, BD);
ID.AddPointer(Data);
}
static bool classof(const LocationContext *Ctx) {
return Ctx->getKind() == Block;
static bool classof(const LocationContext *LC) {
return LC->getKind() == Block;
}
};
class LocationContextManager {
llvm::FoldingSet<LocationContext> Contexts;
/// ID used for generating a new location context.
// ID used for generating a new location context.
int64_t NewID = 0;
public:
~LocationContextManager();
const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
const LocationContext *parent,
const Stmt *s, const CFGBlock *blk,
unsigned blockCount, unsigned idx);
const ScopeContext *getScope(AnalysisDeclContext *ctx,
const LocationContext *parent,
const Stmt *s);
/// Obtain a context of the call stack using its parent context.
///
/// \param ADC The AnalysisDeclContext.
/// \param ParentLC The parent context of this newly created context.
/// \param S The call.
/// \param Block The basic block.
/// \param BlockCount The current count of entering into \p Blk.
/// \param Index The index of \p Blk.
/// \returns The context for \p D with parent context \p ParentLC.
const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
const LocationContext *ParentLC,
const Stmt *S, const CFGBlock *Block,
unsigned BlockCount, unsigned Index);
/// Obtain a context of the block invocation using its parent context.
///
/// \param ADC The AnalysisDeclContext.
/// \param ParentLC The parent context of this newly created context.
/// \param BD The BlockDecl.
/// \param Data The raw data to store as part of the context.
const BlockInvocationContext *
getBlockInvocationContext(AnalysisDeclContext *ctx,
const LocationContext *parent,
const BlockDecl *BD,
const void *ContextData);
getBlockInvocationContext(AnalysisDeclContext *ADC,
const LocationContext *ParentLC,
const BlockDecl *BD, const void *Data);
/// Discard all previously created LocationContext objects.
void clear();
private:
template <typename LOC, typename DATA>
const LOC *getLocationContext(AnalysisDeclContext *ctx,
const LocationContext *parent,
const DATA *d);
};
class AnalysisDeclContextManager {
@ -441,36 +421,31 @@ class AnalysisDeclContextManager {
llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>;
ContextMap Contexts;
LocationContextManager LocContexts;
LocationContextManager LocCtxMgr;
CFG::BuildOptions cfgBuildOptions;
/// Pointer to an interface that can provide function bodies for
/// declarations from external source.
// Pointer to an interface that can provide function bodies for
// declarations from external source.
std::unique_ptr<CodeInjector> Injector;
/// A factory for creating and caching implementations for common
/// methods during the analysis.
// A factory for creating and caching implementations for common
// methods during the analysis.
BodyFarm FunctionBodyFarm;
/// Flag to indicate whether or not bodies should be synthesized
/// for well-known functions.
// Flag to indicate whether or not bodies should be synthesized
// for well-known functions.
bool SynthesizeBodies;
public:
AnalysisDeclContextManager(ASTContext &ASTCtx, bool useUnoptimizedCFG = false,
bool addImplicitDtors = false,
bool addInitializers = false,
bool addTemporaryDtors = false,
bool addLifetime = false,
bool addLoopExit = false,
bool addScopes = false,
bool synthesizeBodies = false,
bool addStaticInitBranches = false,
bool addCXXNewAllocator = true,
bool addRichCXXConstructors = true,
bool markElidedCXXConstructors = true,
bool addVirtualBaseBranches = true,
CodeInjector *injector = nullptr);
AnalysisDeclContextManager(
ASTContext &ASTCtx, bool useUnoptimizedCFG = false,
bool addImplicitDtors = false, bool addInitializers = false,
bool addTemporaryDtors = false, bool addLifetime = false,
bool addLoopExit = false, bool addScopes = false,
bool synthesizeBodies = false, bool addStaticInitBranches = false,
bool addCXXNewAllocator = true, bool addRichCXXConstructors = true,
bool markElidedCXXConstructors = true, bool addVirtualBaseBranches = true,
CodeInjector *injector = nullptr);
AnalysisDeclContext *getContext(const Decl *D);
@ -478,37 +453,27 @@ public:
return !cfgBuildOptions.PruneTriviallyFalseEdges;
}
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
}
CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
/// Return true if faux bodies should be synthesized for well-known
/// functions.
/// \returns Whether faux bodies should be synthesized for known functions.
bool synthesizeBodies() const { return SynthesizeBodies; }
const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
const LocationContext *Parent,
const Stmt *S, const CFGBlock *Blk,
unsigned BlockCount, unsigned Idx) {
return LocContexts.getStackFrame(Ctx, Parent, S, Blk, BlockCount, Idx);
}
// Get the top level stack frame.
/// Obtain the beginning context of the analysis.
///
/// \returns The top level stack frame for \p D.
const StackFrameContext *getStackFrame(const Decl *D) {
return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
0, 0);
return LocCtxMgr.getStackFrame(getContext(D), nullptr, nullptr, nullptr, 0,
0);
}
// Get a stack frame with parent.
StackFrameContext const *getStackFrame(const Decl *D,
/// \copydoc LocationContextManager::getStackFrame()
const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
const LocationContext *Parent,
const Stmt *S, const CFGBlock *Blk,
unsigned BlockCount, unsigned Idx) {
return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, BlockCount,
Idx);
const Stmt *S, const CFGBlock *Block,
unsigned BlockCount, unsigned Index) {
return LocCtxMgr.getStackFrame(ADC, Parent, S, Block, BlockCount, Index);
}
/// Get a reference to {@code BodyFarm} instance.
BodyFarm &getBodyFarm();
/// Discard all previously created AnalysisDeclContexts.
@ -517,9 +482,7 @@ public:
private:
friend class AnalysisDeclContext;
LocationContextManager &getLocationContextManager() {
return LocContexts;
}
LocationContextManager &getLocationContextManager() { return LocCtxMgr; }
};
} // namespace clang

View file

@ -41,6 +41,9 @@ public:
/// An implicit or explicit C++ constructor call
Constructor,
/// A C++ inherited constructor produced by a "using T::T" directive
InheritedConstructor,
/// A C++ allocation function call (operator `new`), via C++ new-expression
Allocator,
@ -84,6 +87,9 @@ public:
AnyCall(const CXXConstructExpr *NE)
: E(NE), D(NE->getConstructor()), K(Constructor) {}
AnyCall(const CXXInheritedCtorInitExpr *CIE)
: E(CIE), D(CIE->getConstructor()), K(InheritedConstructor) {}
AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {}
AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {}
@ -114,6 +120,8 @@ public:
return AnyCall(CXDE);
} else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
return AnyCall(CXCE);
} else if (const auto *CXCIE = dyn_cast<CXXInheritedCtorInitExpr>(E)) {
return AnyCall(CXCIE);
} else {
return None;
}
@ -169,6 +177,7 @@ public:
return cast<CallExpr>(E)->getCallReturnType(Ctx);
case Destructor:
case Constructor:
case InheritedConstructor:
case Allocator:
case Deallocator:
return cast<FunctionDecl>(D)->getReturnType();

View file

@ -624,10 +624,10 @@ class CFGBlock {
template <bool IsOtherConst> friend class ElementRefImpl;
using CFGBlockPtr =
typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>;
using CFGElementPtr = typename std::conditional<IsConst, const CFGElement *,
CFGElement *>::type;
using CFGElementPtr =
std::conditional_t<IsConst, const CFGElement *, CFGElement *>;
protected:
CFGBlockPtr Parent;
@ -675,15 +675,14 @@ class CFGBlock {
friend class ElementRefIterator;
using CFGBlockRef =
typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>;
using UnderlayingIteratorTy = typename std::conditional<
using UnderlayingIteratorTy = std::conditional_t<
IsConst,
typename std::conditional<IsReverse,
ElementList::const_reverse_iterator,
ElementList::const_iterator>::type,
typename std::conditional<IsReverse, ElementList::reverse_iterator,
ElementList::iterator>::type>::type;
std::conditional_t<IsReverse, ElementList::const_reverse_iterator,
ElementList::const_iterator>,
std::conditional_t<IsReverse, ElementList::reverse_iterator,
ElementList::iterator>>;
using IteratorTraits = typename std::iterator_traits<UnderlayingIteratorTy>;
using ElementRef = typename CFGBlock::ElementRefImpl<IsConst>;

View file

@ -24,6 +24,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include <memory>
namespace clang {
@ -65,6 +66,11 @@ public:
/// Determine if a declaration should be included in the graph.
static bool includeInGraph(const Decl *D);
/// Determine if a declaration should be included in the graph for the
/// purposes of being a callee. This is similar to includeInGraph except
/// it permits declarations, not just definitions.
static bool includeCalleeInGraph(const Decl *D);
/// Lookup the node for the given declaration.
CallGraphNode *getNode(const Decl *) const;
@ -136,14 +142,23 @@ public:
private:
/// Add the given declaration to the call graph.
void addNodeForDecl(Decl *D, bool IsGlobal);
/// Allocate a new node in the graph.
CallGraphNode *allocateNewNode(Decl *);
};
class CallGraphNode {
public:
using CallRecord = CallGraphNode *;
struct CallRecord {
CallGraphNode *Callee;
Expr *CallExpr;
CallRecord() = default;
CallRecord(CallGraphNode *Callee_, Expr *CallExpr_)
: Callee(Callee_), CallExpr(CallExpr_) {}
// The call destination is the only important data here,
// allow to transparently unwrap into it.
operator CallGraphNode *() const { return Callee; }
};
private:
/// The function/method declaration.
@ -164,24 +179,67 @@ public:
const_iterator begin() const { return CalledFunctions.begin(); }
const_iterator end() const { return CalledFunctions.end(); }
/// Iterator access to callees/children of the node.
llvm::iterator_range<iterator> callees() {
return llvm::make_range(begin(), end());
}
llvm::iterator_range<const_iterator> callees() const {
return llvm::make_range(begin(), end());
}
bool empty() const { return CalledFunctions.empty(); }
unsigned size() const { return CalledFunctions.size(); }
void addCallee(CallGraphNode *N) {
CalledFunctions.push_back(N);
}
void addCallee(CallRecord Call) { CalledFunctions.push_back(Call); }
Decl *getDecl() const { return FD; }
FunctionDecl *getDefinition() const {
return getDecl()->getAsFunction()->getDefinition();
}
void print(raw_ostream &os) const;
void dump() const;
};
// NOTE: we are comparing based on the callee only. So different call records
// (with different call expressions) to the same callee will compare equal!
inline bool operator==(const CallGraphNode::CallRecord &LHS,
const CallGraphNode::CallRecord &RHS) {
return LHS.Callee == RHS.Callee;
}
} // namespace clang
// Graph traits for iteration, viewing.
namespace llvm {
// Specialize DenseMapInfo for clang::CallGraphNode::CallRecord.
template <> struct DenseMapInfo<clang::CallGraphNode::CallRecord> {
static inline clang::CallGraphNode::CallRecord getEmptyKey() {
return clang::CallGraphNode::CallRecord(
DenseMapInfo<clang::CallGraphNode *>::getEmptyKey(),
DenseMapInfo<clang::Expr *>::getEmptyKey());
}
static inline clang::CallGraphNode::CallRecord getTombstoneKey() {
return clang::CallGraphNode::CallRecord(
DenseMapInfo<clang::CallGraphNode *>::getTombstoneKey(),
DenseMapInfo<clang::Expr *>::getTombstoneKey());
}
static unsigned getHashValue(const clang::CallGraphNode::CallRecord &Val) {
// NOTE: we are comparing based on the callee only.
// Different call records with the same callee will compare equal!
return DenseMapInfo<clang::CallGraphNode *>::getHashValue(Val.Callee);
}
static bool isEqual(const clang::CallGraphNode::CallRecord &LHS,
const clang::CallGraphNode::CallRecord &RHS) {
return LHS == RHS;
}
};
// Graph traits for iteration, viewing.
template <> struct GraphTraits<clang::CallGraphNode*> {
using NodeType = clang::CallGraphNode;
using NodeRef = clang::CallGraphNode *;

View file

@ -110,6 +110,9 @@ public:
ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
: Data(CE), Kind(ArgumentKind), Index(Index) {}
ConstructionContextItem(const CXXInheritedCtorInitExpr *CE, unsigned Index)
: Data(CE), Kind(ArgumentKind), Index(Index) {}
ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
: Data(ME), Kind(ArgumentKind), Index(Index) {}
@ -117,7 +120,7 @@ public:
ConstructionContextItem(const Expr *E, unsigned Index)
: Data(E), Kind(ArgumentKind), Index(Index) {
assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
isa<ObjCMessageExpr>(E));
isa<CXXInheritedCtorInitExpr>(E) || isa<ObjCMessageExpr>(E));
}
ConstructionContextItem(const CXXCtorInitializer *Init)

View file

@ -168,4 +168,4 @@ protected:
};
} // end namespace clang
#endif
#endif // LLVM_CLANG_ANALYSES_DATAFLOW_VALUES

View file

@ -0,0 +1,94 @@
//===- DataflowWorklist.h ---------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// A simple and reusable worklist for flow-sensitive analyses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWWORKLIST_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWWORKLIST_H
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/PriorityQueue.h"
namespace clang {
/// A worklist implementation where the enqueued blocks will be dequeued based
/// on the order defined by 'Comp'.
template <typename Comp, unsigned QueueSize> class DataflowWorklistBase {
llvm::BitVector EnqueuedBlocks;
PostOrderCFGView *POV;
llvm::PriorityQueue<const CFGBlock *,
SmallVector<const CFGBlock *, QueueSize>, Comp>
WorkList;
public:
DataflowWorklistBase(const CFG &Cfg, PostOrderCFGView *POV, Comp C)
: EnqueuedBlocks(Cfg.getNumBlockIDs()), POV(POV), WorkList(C) {}
const PostOrderCFGView *getCFGView() const { return POV; }
void enqueueBlock(const CFGBlock *Block) {
if (Block && !EnqueuedBlocks[Block->getBlockID()]) {
EnqueuedBlocks[Block->getBlockID()] = true;
WorkList.push(Block);
}
}
const CFGBlock *dequeue() {
if (WorkList.empty())
return nullptr;
const CFGBlock *B = WorkList.top();
WorkList.pop();
EnqueuedBlocks[B->getBlockID()] = false;
return B;
}
};
struct ReversePostOrderCompare {
PostOrderCFGView::BlockOrderCompare Cmp;
bool operator()(const CFGBlock *lhs, const CFGBlock *rhs) const {
return Cmp(rhs, lhs);
}
};
/// A worklist implementation for forward dataflow analysis. The enqueued
/// blocks will be dequeued in reverse post order. The worklist cannot contain
/// the same block multiple times at once.
struct ForwardDataflowWorklist
: DataflowWorklistBase<ReversePostOrderCompare, 20> {
ForwardDataflowWorklist(const CFG &Cfg, AnalysisDeclContext &Ctx)
: DataflowWorklistBase(
Cfg, Ctx.getAnalysis<PostOrderCFGView>(),
ReversePostOrderCompare{
Ctx.getAnalysis<PostOrderCFGView>()->getComparator()}) {}
void enqueueSuccessors(const CFGBlock *Block) {
for (auto B : Block->succs())
enqueueBlock(B);
}
};
/// A worklist implementation for backward dataflow analysis. The enqueued
/// block will be dequeued in post order. The worklist cannot contain the same
/// block multiple times at once.
struct BackwardDataflowWorklist
: DataflowWorklistBase<PostOrderCFGView::BlockOrderCompare, 20> {
BackwardDataflowWorklist(const CFG &Cfg, AnalysisDeclContext &Ctx)
: DataflowWorklistBase(
Cfg, Ctx.getAnalysis<PostOrderCFGView>(),
Ctx.getAnalysis<PostOrderCFGView>()->getComparator()) {}
void enqueuePredecessors(const CFGBlock *Block) {
for (auto B : Block->preds())
enqueueBlock(B);
}
};
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H

View file

@ -561,7 +561,7 @@ public:
void setCallee(const CallEnter &CE, const SourceManager &SM);
bool hasCallStackMessage() { return !CallStackMessage.empty(); }
void setCallStackMessage(StringRef st) { CallStackMessage = st; }
void setCallStackMessage(StringRef st) { CallStackMessage = std::string(st); }
PathDiagnosticLocation getLocation() const override { return callEnter; }
@ -806,7 +806,7 @@ public:
meta_iterator meta_begin() const { return OtherDesc.begin(); }
meta_iterator meta_end() const { return OtherDesc.end(); }
void addMeta(StringRef s) { OtherDesc.push_back(s); }
void addMeta(StringRef s) { OtherDesc.push_back(std::string(s)); }
const FilesToLineNumsMap &getExecutedLines() const {
return *ExecutedLines;

View file

@ -35,35 +35,95 @@
//
// - IsFP is true for vectors of floating-point elements.
//
// - IsBF true for vector of brain float elements.
//===----------------------------------------------------------------------===//
#ifndef SVE_VECTOR_TYPE
#define SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP)\
#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId, NumEls, ElBits, \
IsSigned, IsFP, IsBF) \
SVE_TYPE(Name, Id, SingletonId)
#endif
#ifndef SVE_PREDICATE_TYPE
#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind)\
#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId, NumEls) \
SVE_TYPE(Name, Id, SingletonId)
#endif
//===- Vector point types -----------------------------------------------===//
SVE_VECTOR_TYPE("__SVInt8_t", SveInt8, SveInt8Ty, SveElSInt8, 8, true, false)
SVE_VECTOR_TYPE("__SVInt16_t", SveInt16, SveInt16Ty, SveElSInt16, 16, true, false)
SVE_VECTOR_TYPE("__SVInt32_t", SveInt32, SveInt32Ty, SveElSInt32, 32, true, false)
SVE_VECTOR_TYPE("__SVInt64_t", SveInt64, SveInt64Ty, SveElSInt64, 64, true, false)
SVE_VECTOR_TYPE("__SVUint8_t", SveUint8, SveUint8Ty, SveElUInt8, 8, false, false)
SVE_VECTOR_TYPE("__SVUint16_t", SveUint16, SveUint16Ty, SveElUInt16, 16, false, false)
SVE_VECTOR_TYPE("__SVUint32_t", SveUint32, SveUint32Ty, SveElUInt32, 32, false, false)
SVE_VECTOR_TYPE("__SVUint64_t", SveUint64, SveUint64Ty, SveElUInt64, 64, false, false)
SVE_VECTOR_TYPE("__SVInt8_t", "__SVInt8_t", SveInt8, SveInt8Ty, 16, 8, true, false, false)
SVE_VECTOR_TYPE("__SVInt16_t", "__SVInt16_t", SveInt16, SveInt16Ty, 8, 16, true, false, false)
SVE_VECTOR_TYPE("__SVInt32_t", "__SVInt32_t", SveInt32, SveInt32Ty, 4, 32, true, false, false)
SVE_VECTOR_TYPE("__SVInt64_t", "__SVInt64_t", SveInt64, SveInt64Ty, 2, 64, true, false, false)
SVE_VECTOR_TYPE("__SVFloat16_t", SveFloat16, SveFloat16Ty, SveElHalf, 16, true, true)
SVE_VECTOR_TYPE("__SVFloat32_t", SveFloat32, SveFloat32Ty, SveElFloat, 32, true, true)
SVE_VECTOR_TYPE("__SVFloat64_t", SveFloat64, SveFloat64Ty, SveElDouble, 64, true, true)
SVE_VECTOR_TYPE("__SVUint8_t", "__SVUint8_t", SveUint8, SveUint8Ty, 16, 8, false, false, false)
SVE_VECTOR_TYPE("__SVUint16_t", "__SVUint16_t", SveUint16, SveUint16Ty, 8, 16, false, false, false)
SVE_VECTOR_TYPE("__SVUint32_t", "__SVUint32_t", SveUint32, SveUint32Ty, 4, 32, false, false, false)
SVE_VECTOR_TYPE("__SVUint64_t", "__SVUint64_t", SveUint64, SveUint64Ty, 2, 64, false, false, false)
SVE_PREDICATE_TYPE("__SVBool_t", SveBool, SveBoolTy, SveElBool)
SVE_VECTOR_TYPE("__SVFloat16_t", "__SVFloat16_t", SveFloat16, SveFloat16Ty, 8, 16, true, true, false)
SVE_VECTOR_TYPE("__SVFloat32_t", "__SVFloat32_t", SveFloat32, SveFloat32Ty, 4, 32, true, true, false)
SVE_VECTOR_TYPE("__SVFloat64_t", "__SVFloat64_t", SveFloat64, SveFloat64Ty, 2, 64, true, true, false)
SVE_VECTOR_TYPE("__SVBFloat16_t", "__SVBFloat16_t", SveBFloat16, SveBFloat16Ty, 8, 16, true, false, true)
//
// x2
//
SVE_VECTOR_TYPE("__clang_svint8x2_t", "svint8x2_t", SveInt8x2, SveInt8x2Ty, 32, 8, true, false, false)
SVE_VECTOR_TYPE("__clang_svint16x2_t", "svint16x2_t", SveInt16x2, SveInt16x2Ty, 16, 16, true, false, false)
SVE_VECTOR_TYPE("__clang_svint32x2_t", "svint32x2_t", SveInt32x2, SveInt32x2Ty, 8, 32, true, false, false)
SVE_VECTOR_TYPE("__clang_svint64x2_t", "svint64x2_t", SveInt64x2, SveInt64x2Ty, 4, 64, true, false, false)
SVE_VECTOR_TYPE("__clang_svuint8x2_t", "svuint8x2_t", SveUint8x2, SveUint8x2Ty, 32, 8, false, false, false)
SVE_VECTOR_TYPE("__clang_svuint16x2_t", "svuint16x2_t", SveUint16x2, SveUint16x2Ty, 16, 16, false, false, false)
SVE_VECTOR_TYPE("__clang_svuint32x2_t", "svuint32x2_t", SveUint32x2, SveUint32x2Ty, 8, 32, false, false, false)
SVE_VECTOR_TYPE("__clang_svuint64x2_t", "svuint64x2_t", SveUint64x2, SveUint64x2Ty, 4, 64, false, false, false)
SVE_VECTOR_TYPE("__clang_svfloat16x2_t", "svfloat16x2_t", SveFloat16x2, SveFloat16x2Ty, 16, 16, true, true, false)
SVE_VECTOR_TYPE("__clang_svfloat32x2_t", "svfloat32x2_t", SveFloat32x2, SveFloat32x2Ty, 8, 32, true, true, false)
SVE_VECTOR_TYPE("__clang_svfloat64x2_t", "svfloat64x2_t", SveFloat64x2, SveFloat64x2Ty, 4, 64, true, true, false)
SVE_VECTOR_TYPE("__clang_svbfloat16x2_t", "svbfloat16x2_t", SveBFloat16x2, SveBFloat16x2Ty, 16, 16, true, false, true)
//
// x3
//
SVE_VECTOR_TYPE("__clang_svint8x3_t", "svint8x3_t", SveInt8x3, SveInt8x3Ty, 48, 8, true, false, false)
SVE_VECTOR_TYPE("__clang_svint16x3_t", "svint16x3_t", SveInt16x3, SveInt16x3Ty, 24, 16, true, false, false)
SVE_VECTOR_TYPE("__clang_svint32x3_t", "svint32x3_t", SveInt32x3, SveInt32x3Ty, 12, 32, true, false, false)
SVE_VECTOR_TYPE("__clang_svint64x3_t", "svint64x3_t", SveInt64x3, SveInt64x3Ty, 6, 64, true, false, false)
SVE_VECTOR_TYPE("__clang_svuint8x3_t", "svuint8x3_t", SveUint8x3, SveUint8x3Ty, 48, 8, false, false, false)
SVE_VECTOR_TYPE("__clang_svuint16x3_t", "svuint16x3_t", SveUint16x3, SveUint16x3Ty, 24, 16, false, false, false)
SVE_VECTOR_TYPE("__clang_svuint32x3_t", "svuint32x3_t", SveUint32x3, SveUint32x3Ty, 12, 32, false, false, false)
SVE_VECTOR_TYPE("__clang_svuint64x3_t", "svuint64x3_t", SveUint64x3, SveUint64x3Ty, 6, 64, false, false, false)
SVE_VECTOR_TYPE("__clang_svfloat16x3_t", "svfloat16x3_t", SveFloat16x3, SveFloat16x3Ty, 24, 16, true, true, false)
SVE_VECTOR_TYPE("__clang_svfloat32x3_t", "svfloat32x3_t", SveFloat32x3, SveFloat32x3Ty, 12, 32, true, true, false)
SVE_VECTOR_TYPE("__clang_svfloat64x3_t", "svfloat64x3_t", SveFloat64x3, SveFloat64x3Ty, 6, 64, true, true, false)
SVE_VECTOR_TYPE("__clang_svbfloat16x3_t", "svbfloat16x3_t", SveBFloat16x3, SveBFloat16x3Ty, 24, 16, true, false, true)
//
// x4
//
SVE_VECTOR_TYPE("__clang_svint8x4_t", "svint8x4_t", SveInt8x4, SveInt8x4Ty, 64, 8, true, false, false)
SVE_VECTOR_TYPE("__clang_svint16x4_t", "svint16x4_t", SveInt16x4, SveInt16x4Ty, 32, 16, true, false, false)
SVE_VECTOR_TYPE("__clang_svint32x4_t", "svint32x4_t", SveInt32x4, SveInt32x4Ty, 16, 32, true, false, false)
SVE_VECTOR_TYPE("__clang_svint64x4_t", "svint64x4_t", SveInt64x4, SveInt64x4Ty, 8, 64, true, false, false)
SVE_VECTOR_TYPE("__clang_svuint8x4_t", "svuint8x4_t", SveUint8x4, SveUint8x4Ty, 64, 8, false, false, false)
SVE_VECTOR_TYPE("__clang_svuint16x4_t", "svuint16x4_t", SveUint16x4, SveUint16x4Ty, 32, 16, false, false, false)
SVE_VECTOR_TYPE("__clang_svuint32x4_t", "svuint32x4_t", SveUint32x4, SveUint32x4Ty, 16, 32, false, false, false)
SVE_VECTOR_TYPE("__clang_svuint64x4_t", "svuint64x4_t", SveUint64x4, SveUint64x4Ty, 8, 64, false, false, false)
SVE_VECTOR_TYPE("__clang_svfloat16x4_t", "svfloat16x4_t", SveFloat16x4, SveFloat16x4Ty, 32, 16, true, true, false)
SVE_VECTOR_TYPE("__clang_svfloat32x4_t", "svfloat32x4_t", SveFloat32x4, SveFloat32x4Ty, 16, 32, true, true, false)
SVE_VECTOR_TYPE("__clang_svfloat64x4_t", "svfloat64x4_t", SveFloat64x4, SveFloat64x4Ty, 8, 64, true, true, false)
SVE_VECTOR_TYPE("__clang_svbfloat16x4_t", "svbfloat16x4_t", SveBFloat16x4, SveBFloat16x4Ty, 32, 16, true, false, true)
SVE_PREDICATE_TYPE("__SVBool_t", "__SVBool_t", SveBool, SveBoolTy, 16)
#undef SVE_VECTOR_TYPE
#undef SVE_PREDICATE_TYPE

View file

@ -174,12 +174,31 @@ class IdentifierArgument<string name, bit opt = 0> : Argument<name, opt>;
class IntArgument<string name, bit opt = 0> : Argument<name, opt>;
class StringArgument<string name, bit opt = 0> : Argument<name, opt>;
class ExprArgument<string name, bit opt = 0> : Argument<name, opt>;
class FunctionArgument<string name, bit opt = 0, bit fake = 0> : Argument<name,
opt,
fake>;
class NamedArgument<string name, bit opt = 0, bit fake = 0> : Argument<name,
opt,
fake>;
class DeclArgument<DeclNode kind, string name, bit opt = 0, bit fake = 0>
: Argument<name, opt, fake> {
DeclNode Kind = kind;
}
// An argument of a OMPDeclareVariantAttr that represents the `match`
// clause of the declare variant by keeping the information (incl. nesting) in
// an OMPTraitInfo object.
//
// With some exceptions, the `match(<context-selector>)` clause looks roughly
// as follows:
// context-selector := list<selector-set>
// selector-set := <kind>={list<selector>}
// selector := <kind>([score(<const-expr>):] list<trait>)
// trait := <kind>
//
// The structure of an OMPTraitInfo object is a tree as defined below:
//
// OMPTraitInfo := {list<OMPTraitSet>}
// OMPTraitSet := {Kind, list<OMPTraitSelector>}
// OMPTraitSelector := {Kind, Expr, list<OMPTraitProperty>}
// OMPTraitProperty := {Kind}
//
class OMPTraitInfoArgument<string name> : Argument<name, 0>;
class TypeArgument<string name, bit opt = 0> : Argument<name, opt>;
class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;
class VariadicUnsignedArgument<string name> : Argument<name, 1>;
@ -238,7 +257,6 @@ class VariadicEnumArgument<string name, string type, list<string> values,
class Spelling<string name, string variety> {
string Name = name;
string Variety = variety;
bit KnownToGCC;
}
class GNU<string name> : Spelling<name, "GNU">;
@ -258,11 +276,11 @@ class Pragma<string namespace, string name> : Spelling<name, "Pragma"> {
string Namespace = namespace;
}
// The GCC spelling implies GNU<name> and CXX11<"gnu", name> and also sets
// KnownToGCC to 1. This spelling should be used for any GCC-compatible
// The GCC spelling implies GNU<name>, CXX11<"gnu", name>, and optionally,
// C2x<"gnu", name>. This spelling should be used for any GCC-compatible
// attributes.
class GCC<string name> : Spelling<name, "GCC"> {
let KnownToGCC = 1;
class GCC<string name, bit allowInC = 1> : Spelling<name, "GCC"> {
bit AllowInC = allowInC;
}
// The Clang spelling implies GNU<name>, CXX11<"clang", name>, and optionally,
@ -291,6 +309,7 @@ class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag,
}
class LangOpt<string name, code customCode = [{}]> {
// The language option to test; ignored when custom code is supplied.
string Name = name;
// A custom predicate, written as an expression evaluated in a context with
@ -300,17 +319,16 @@ class LangOpt<string name, code customCode = [{}]> {
def MicrosoftExt : LangOpt<"MicrosoftExt">;
def Borland : LangOpt<"Borland">;
def CUDA : LangOpt<"CUDA">;
def HIP : LangOpt<"HIP">;
def SYCL : LangOpt<"SYCLIsDevice">;
def COnly : LangOpt<"COnly", "!LangOpts.CPlusPlus">;
def COnly : LangOpt<"", "!LangOpts.CPlusPlus">;
def CPlusPlus : LangOpt<"CPlusPlus">;
def OpenCL : LangOpt<"OpenCL">;
def RenderScript : LangOpt<"RenderScript">;
def ObjC : LangOpt<"ObjC">;
def BlocksSupported : LangOpt<"Blocks">;
def ObjCAutoRefCount : LangOpt<"ObjCAutoRefCount">;
def ObjCNonFragileRuntime : LangOpt<"ObjCNonFragileRuntime",
"LangOpts.ObjCRuntime.allowsClassStubs()">;
def ObjCNonFragileRuntime
: LangOpt<"", "LangOpts.ObjCRuntime.allowsClassStubs()">;
// Language option for CMSE extensions
def Cmse : LangOpt<"Cmse">;
@ -337,6 +355,8 @@ class TargetArch<list<string> arches> : TargetSpec {
let Arches = arches;
}
def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
def TargetAArch64 : TargetArch<["aarch64"]>;
def TargetAnyArm : TargetArch<!listconcat(TargetARM.Arches, TargetAArch64.Arches)>;
def TargetAVR : TargetArch<["avr"]>;
def TargetBPF : TargetArch<["bpfel", "bpfeb"]>;
def TargetMips32 : TargetArch<["mips", "mipsel"]>;
@ -420,6 +440,7 @@ def SubjectMatcherForEnumConstant : AttrSubjectMatcherRule<"enum_constant",
def SubjectMatcherForVar : AttrSubjectMatcherRule<"variable", [Var], [
AttrSubjectMatcherSubRule<"is_thread_local", [TLSVar]>,
AttrSubjectMatcherSubRule<"is_global", [GlobalVar]>,
AttrSubjectMatcherSubRule<"is_local", [LocalVar]>,
AttrSubjectMatcherSubRule<"is_parameter", [ParmVar]>,
// unless(is_parameter)
AttrSubjectMatcherSubRule<"is_parameter", [NonParmVar], 1>
@ -489,6 +510,8 @@ class Attr {
bit ASTNode = 1;
// Set to true for attributes which have handler in Sema.
bit SemaHandler = 1;
// Set to true if this attribute doesn't need custom handling in Sema.
bit SimpleHandler = 0;
// Set to true for attributes that are completely ignored.
bit Ignored = 0;
// Set to true if the attribute's parsing does not match its semantic
@ -581,7 +604,7 @@ class IgnoredAttr : Attr {
//
def AbiTag : Attr {
let Spellings = [GCC<"abi_tag">];
let Spellings = [GCC<"abi_tag", /*AllowInC*/0>];
let Args = [VariadicStringArgument<"Tags">];
let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag>;
let MeaningfulToClassTemplateDefinition = 1;
@ -601,11 +624,11 @@ def Alias : Attr {
let Documentation = [Undocumented];
}
def ArmMveAlias : InheritableAttr, TargetSpecificAttr<TargetARM> {
let Spellings = [Clang<"__clang_arm_mve_alias">];
def ArmBuiltinAlias : InheritableAttr, TargetSpecificAttr<TargetAnyArm> {
let Spellings = [Clang<"__clang_arm_builtin_alias">];
let Args = [IdentifierArgument<"BuiltinName">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [ArmMveAliasDocs];
let Documentation = [ArmBuiltinAliasDocs];
}
def Aligned : InheritableAttr {
@ -655,8 +678,9 @@ def AlwaysInline : InheritableAttr {
def Artificial : InheritableAttr {
let Spellings = [GCC<"artificial">];
let Subjects = SubjectList<[InlineFunction], WarnDiag>;
let Subjects = SubjectList<[InlineFunction]>;
let Documentation = [ArtificialDocs];
let SimpleHandler = 1;
}
def XRayInstrument : InheritableAttr {
@ -668,6 +692,7 @@ def XRayInstrument : InheritableAttr {
Accessor<"neverXRayInstrument",
[Clang<"xray_never_instrument">]>];
let Documentation = [XRayDocs];
let SimpleHandler = 1;
}
def XRayLogArgs : InheritableAttr {
@ -924,15 +949,29 @@ def OSConsumesThis : InheritableAttr {
let Spellings = [Clang<"os_consumes_this">];
let Subjects = SubjectList<[NonStaticCXXMethod]>;
let Documentation = [RetainBehaviorDocs];
let SimpleHandler = 1;
}
def Cleanup : InheritableAttr {
let Spellings = [GCC<"cleanup">];
let Args = [FunctionArgument<"FunctionDecl">];
let Args = [DeclArgument<Function, "FunctionDecl">];
let Subjects = SubjectList<[LocalVar]>;
let Documentation = [Undocumented];
}
def CmseNSEntry : InheritableAttr, TargetSpecificAttr<TargetARM> {
let Spellings = [GNU<"cmse_nonsecure_entry">];
let Subjects = SubjectList<[Function]>;
let LangOpts = [Cmse];
let Documentation = [ArmCmseNSEntryDocs];
}
def CmseNSCall : TypeAttr, TargetSpecificAttr<TargetARM> {
let Spellings = [GNU<"cmse_nonsecure_call">];
let LangOpts = [Cmse];
let Documentation = [ArmCmseNSCallDocs];
}
def Cold : InheritableAttr {
let Spellings = [GCC<"cold">];
let Subjects = SubjectList<[Function]>;
@ -948,6 +987,7 @@ def Common : InheritableAttr {
def Const : InheritableAttr {
let Spellings = [GCC<"const">, GCC<"__const">];
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def ConstInit : InheritableAttr {
@ -959,6 +999,7 @@ def ConstInit : InheritableAttr {
let Accessors = [Accessor<"isConstinit", [Keyword<"constinit">]>];
let Documentation = [ConstInitDocs];
let LangOpts = [CPlusPlus];
let SimpleHandler = 1;
}
def Constructor : InheritableAttr {
@ -1008,28 +1049,25 @@ def CUDADevice : InheritableAttr {
let Documentation = [Undocumented];
}
def HIPPinnedShadow : InheritableAttr {
let Spellings = [GNU<"hip_pinned_shadow">, Declspec<"__hip_pinned_shadow__">];
let Subjects = SubjectList<[Var]>;
let LangOpts = [HIP];
let Documentation = [HIPPinnedShadowDocs];
}
def CUDADeviceBuiltin : IgnoredAttr {
let Spellings = [GNU<"device_builtin">, Declspec<"__device_builtin__">];
let LangOpts = [CUDA];
}
def CUDADeviceBuiltinSurfaceType : IgnoredAttr {
def CUDADeviceBuiltinSurfaceType : InheritableAttr {
let Spellings = [GNU<"device_builtin_surface_type">,
Declspec<"__device_builtin_surface_type__">];
let LangOpts = [CUDA];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [CUDADeviceBuiltinSurfaceTypeDocs];
}
def CUDADeviceBuiltinTextureType : IgnoredAttr {
def CUDADeviceBuiltinTextureType : InheritableAttr {
let Spellings = [GNU<"device_builtin_texture_type">,
Declspec<"__device_builtin_texture_type__">];
let LangOpts = [CUDA];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [CUDADeviceBuiltinTextureTypeDocs];
}
def CUDAGlobal : InheritableAttr {
@ -1089,6 +1127,7 @@ def CXX11NoReturn : InheritableAttr {
let Spellings = [CXX11<"", "noreturn", 200809>];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [CXX11NoReturnDocs];
let SimpleHandler = 1;
}
// Similar to CUDA, OpenCL attributes do not receive a [[]] spelling because
@ -1097,6 +1136,7 @@ def OpenCLKernel : InheritableAttr {
let Spellings = [Keyword<"__kernel">, Keyword<"kernel">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def OpenCLUnrollHint : InheritableAttr {
@ -1166,6 +1206,7 @@ def RenderScriptKernel : Attr {
let Subjects = SubjectList<[Function]>;
let Documentation = [RenderScriptKernelAttributeDocs];
let LangOpts = [RenderScript];
let SimpleHandler = 1;
}
def Deprecated : InheritableAttr {
@ -1190,6 +1231,7 @@ def EmptyBases : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Spellings = [Declspec<"empty_bases">];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [EmptyBasesDocs];
let SimpleHandler = 1;
}
def AllocSize : InheritableAttr {
@ -1232,6 +1274,11 @@ def FallThrough : StmtAttr {
let Documentation = [FallthroughDocs];
}
def NoMerge : StmtAttr {
let Spellings = [Clang<"nomerge">];
let Documentation = [NoMergeDocs];
}
def FastCall : DeclOrTypeAttr {
let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
Keyword<"_fastcall">];
@ -1261,6 +1308,7 @@ def FlagEnum : InheritableAttr {
let Spellings = [Clang<"flag_enum">];
let Subjects = SubjectList<[Enum]>;
let Documentation = [FlagEnumDocs];
let SimpleHandler = 1;
}
def EnumExtensibility : InheritableAttr {
@ -1275,6 +1323,7 @@ def Flatten : InheritableAttr {
let Spellings = [GCC<"flatten">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [FlattenDocs];
let SimpleHandler = 1;
}
def Format : InheritableAttr {
@ -1320,6 +1369,7 @@ def IBAction : InheritableAttr {
// of the compiler. However, this node needs to exist in the AST because
// external tools rely on it.
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def IBOutlet : InheritableAttr {
@ -1360,6 +1410,7 @@ def LifetimeBound : DeclOrTypeAttr {
let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;
let Documentation = [LifetimeBoundDocs];
let LangOpts = [CPlusPlus];
let SimpleHandler = 1;
}
def TrivialABI : InheritableAttr {
@ -1369,6 +1420,7 @@ def TrivialABI : InheritableAttr {
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [TrivialABIDocs];
let LangOpts = [CPlusPlus];
let SimpleHandler = 1;
}
def MaxFieldAlignment : InheritableAttr {
@ -1383,6 +1435,7 @@ def MayAlias : InheritableAttr {
// FIXME: this is a type attribute in GCC, but a declaration attribute here.
let Spellings = [GCC<"may_alias">];
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def MIGServerRoutine : InheritableAttr {
@ -1479,16 +1532,23 @@ def NeonVectorType : TypeAttr {
let ASTNode = 0;
}
def ArmMveStrictPolymorphism : TypeAttr, TargetSpecificAttr<TargetARM> {
let Spellings = [Clang<"__clang_arm_mve_strict_polymorphism">];
let Documentation = [ArmMveStrictPolymorphismDocs];
}
def NoUniqueAddress : InheritableAttr, TargetSpecificAttr<TargetItaniumCXXABI> {
let Spellings = [CXX11<"", "no_unique_address", 201803>];
let Subjects = SubjectList<[NonBitField], ErrorDiag>;
let Documentation = [NoUniqueAddressDocs];
let SimpleHandler = 1;
}
def ReturnsTwice : InheritableAttr {
let Spellings = [GCC<"returns_twice">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def DisableTailCalls : InheritableAttr {
@ -1501,12 +1561,14 @@ def NoAlias : InheritableAttr {
let Spellings = [Declspec<"noalias">];
let Subjects = SubjectList<[Function]>;
let Documentation = [NoAliasDocs];
let SimpleHandler = 1;
}
def NoCommon : InheritableAttr {
let Spellings = [GCC<"nocommon">];
let Subjects = SubjectList<[Var]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def NoDebug : InheritableAttr {
@ -1519,30 +1581,35 @@ def NoDuplicate : InheritableAttr {
let Spellings = [Clang<"noduplicate">];
let Subjects = SubjectList<[Function]>;
let Documentation = [NoDuplicateDocs];
let SimpleHandler = 1;
}
def Convergent : InheritableAttr {
let Spellings = [Clang<"convergent">];
let Subjects = SubjectList<[Function]>;
let Documentation = [ConvergentDocs];
let SimpleHandler = 1;
}
def NoInline : InheritableAttr {
let Spellings = [GCC<"noinline">, Declspec<"noinline">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Spellings = [GCC<"nomips16">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Spellings = [GCC<"nomicromips">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [MicroMipsDocs];
let SimpleHandler = 1;
}
def RISCVInterrupt : InheritableAttr, TargetSpecificAttr<TargetRISCV> {
@ -1637,6 +1704,7 @@ def NoSplitStack : InheritableAttr {
let Spellings = [GCC<"no_split_stack">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [NoSplitStackDocs];
let SimpleHandler = 1;
}
def NonNull : InheritableParamAttr {
@ -1734,6 +1802,7 @@ def NoInstrumentFunction : InheritableAttr {
let Spellings = [GCC<"no_instrument_function">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def NotTailCalled : InheritableAttr {
@ -1746,6 +1815,7 @@ def NoStackProtector : InheritableAttr {
let Spellings = [Clang<"no_stack_protector">];
let Subjects = SubjectList<[Function]>;
let Documentation = [NoStackProtectorDocs];
let SimpleHandler = 1;
}
def NoThrow : InheritableAttr {
@ -1808,6 +1878,7 @@ def NSConsumesSelf : InheritableAttr {
let Spellings = [Clang<"ns_consumes_self">];
let Subjects = SubjectList<[ObjCMethod]>;
let Documentation = [RetainBehaviorDocs];
let SimpleHandler = 1;
}
def NSConsumed : InheritableParamAttr {
@ -1820,6 +1891,7 @@ def ObjCException : InheritableAttr {
let Spellings = [Clang<"objc_exception">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def ObjCMethodFamily : InheritableAttr {
@ -1864,6 +1936,7 @@ def ObjCRootClass : InheritableAttr {
let Spellings = [Clang<"objc_root_class">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def ObjCNonLazyClass : Attr {
@ -1871,12 +1944,14 @@ def ObjCNonLazyClass : Attr {
let Subjects = SubjectList<[ObjCInterface, ObjCImpl], ErrorDiag>;
let LangOpts = [ObjC];
let Documentation = [ObjCNonLazyClassDocs];
let SimpleHandler = 1;
}
def ObjCSubclassingRestricted : InheritableAttr {
let Spellings = [Clang<"objc_subclassing_restricted">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [ObjCSubclassingRestrictedDocs];
let SimpleHandler = 1;
}
def ObjCExplicitProtocolImpl : InheritableAttr {
@ -1900,7 +1975,7 @@ def ObjCDirect : Attr {
def ObjCDirectMembers : Attr {
let Spellings = [Clang<"objc_direct_members">];
let Subjects = SubjectList<[ObjCImpl, ObjCCategory], ErrorDiag>;
let Subjects = SubjectList<[ObjCImpl, ObjCInterface, ObjCCategory], ErrorDiag>;
let LangOpts = [ObjC];
let Documentation = [ObjCDirectMembersDocs];
}
@ -1916,6 +1991,7 @@ def ObjCRuntimeVisible : Attr {
let Spellings = [Clang<"objc_runtime_visible">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [ObjCRuntimeVisibleDocs];
let SimpleHandler = 1;
}
def ObjCClassStub : Attr {
@ -1923,6 +1999,7 @@ def ObjCClassStub : Attr {
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [ObjCClassStubDocs];
let LangOpts = [ObjCNonFragileRuntime];
let SimpleHandler = 1;
}
def ObjCBoxable : Attr {
@ -1941,6 +2018,7 @@ def Overloadable : Attr {
let Spellings = [Clang<"overloadable">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [OverloadableDocs];
let SimpleHandler = 1;
}
def Override : InheritableAttr {
@ -1998,6 +2076,7 @@ def AArch64VectorPcs: DeclOrTypeAttr {
def Pure : InheritableAttr {
let Spellings = [GCC<"pure">];
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def Regparm : TypeAttr {
@ -2033,7 +2112,7 @@ def WorkGroupSizeHint : InheritableAttr {
}
def InitPriority : InheritableAttr {
let Spellings = [GCC<"init_priority">];
let Spellings = [GCC<"init_priority", /*AllowInC*/0>];
let Args = [UnsignedArgument<"Priority">];
let Subjects = SubjectList<[Var], ErrorDiag>;
let Documentation = [Undocumented];
@ -2306,7 +2385,7 @@ def DiagnoseIf : InheritableAttr {
["error", "warning"],
["DT_Error", "DT_Warning"]>,
BoolArgument<"ArgDependent", 0, /*fake*/ 1>,
NamedArgument<"Parent", 0, /*fake*/ 1>];
DeclArgument<Named, "Parent", 0, /*fake*/ 1>];
let InheritEvenIfAlreadyPresent = 1;
let LateParsed = 1;
let AdditionalMembers = [{
@ -2321,6 +2400,7 @@ def ArcWeakrefUnavailable : InheritableAttr {
let Spellings = [Clang<"objc_arc_weak_reference_unavailable">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def ObjCGC : TypeAttr {
@ -2339,6 +2419,7 @@ def ObjCRequiresPropertyDefs : InheritableAttr {
let Spellings = [Clang<"objc_requires_property_definitions">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def Unused : InheritableAttr {
@ -2353,11 +2434,13 @@ def Used : InheritableAttr {
let Spellings = [GCC<"used">];
let Subjects = SubjectList<[NonLocalVar, Function, ObjCMethod]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def Uuid : InheritableAttr {
let Spellings = [Declspec<"uuid">, Microsoft<"uuid">];
let Args = [StringArgument<"Guid">];
let Args = [StringArgument<"Guid">,
DeclArgument<MSGuid, "GuidDecl", 0, /*fake=*/1>];
let Subjects = SubjectList<[Record, Enum]>;
// FIXME: Allow expressing logical AND for LangOpts. Our condition should be:
// CPlusPlus && (MicrosoftExt || Borland)
@ -2381,6 +2464,15 @@ def VecTypeHint : InheritableAttr {
let Documentation = [Undocumented];
}
def MatrixType : TypeAttr {
let Spellings = [Clang<"matrix_type">];
let Subjects = SubjectList<[TypedefName], ErrorDiag>;
let Args = [ExprArgument<"NumRows">, ExprArgument<"NumColumns">];
let Documentation = [Undocumented];
let ASTNode = 0;
let PragmaAttributeSupport = 0;
}
def Visibility : InheritableAttr {
let Clone = 0;
let Spellings = [GCC<"visibility">];
@ -2414,6 +2506,7 @@ def WarnUnused : InheritableAttr {
let Spellings = [GCC<"warn_unused">];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def WarnUnusedResult : InheritableAttr {
@ -2436,6 +2529,7 @@ def Weak : InheritableAttr {
let Spellings = [GCC<"weak">];
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def WeakImport : InheritableAttr {
@ -2455,6 +2549,7 @@ def LTOVisibilityPublic : InheritableAttr {
let Spellings = [Clang<"lto_visibility_public">];
let Subjects = SubjectList<[Record]>;
let Documentation = [LTOVisibilityDocs];
let SimpleHandler = 1;
}
def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
@ -2471,6 +2566,7 @@ def AnyX86NoCallerSavedRegisters : InheritableAttr,
TargetSpecificAttr<TargetAnyX86> {
let Spellings = [GCC<"no_caller_saved_registers">];
let Documentation = [AnyX86NoCallerSavedRegistersDocs];
let SimpleHandler = 1;
}
def AnyX86NoCfCheck : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86>{
@ -2522,6 +2618,7 @@ def CFICanonicalJumpTable : InheritableAttr {
let Spellings = [Clang<"cfi_canonical_jump_table">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [CFICanonicalJumpTableDocs];
let SimpleHandler = 1;
}
// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
@ -2534,6 +2631,7 @@ def GuardedVar : InheritableAttr {
let Spellings = [Clang<"guarded_var", 0>];
let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def PtGuardedVar : InheritableAttr {
@ -2553,6 +2651,7 @@ def ScopedLockable : InheritableAttr {
let Spellings = [Clang<"scoped_lockable", 0>];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def Capability : InheritableAttr {
@ -2562,10 +2661,6 @@ def Capability : InheritableAttr {
let Accessors = [Accessor<"isShared",
[Clang<"shared_capability", 0>]>];
let Documentation = [Undocumented];
let AdditionalMembers = [{
bool isMutex() const { return getName().equals_lower("mutex"); }
bool isRole() const { return getName().equals_lower("role"); }
}];
}
def AssertCapability : InheritableAttr {
@ -2653,6 +2748,7 @@ def NoThreadSafetyAnalysis : InheritableAttr {
let Spellings = [Clang<"no_thread_safety_analysis">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def GuardedBy : InheritableAttr {
@ -2789,6 +2885,7 @@ def ConsumableAutoCast : InheritableAttr {
let Spellings = [Clang<"consumable_auto_cast_state", 0>];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def ConsumableSetOnRead : InheritableAttr {
@ -2798,6 +2895,7 @@ def ConsumableSetOnRead : InheritableAttr {
let Spellings = [Clang<"consumable_set_state_on_read", 0>];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def CallableWhen : InheritableAttr {
@ -2904,6 +3002,7 @@ def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Spellings = [Declspec<"novtable">];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [MSNoVTableDocs];
let SimpleHandler = 1;
}
def : IgnoredAttr {
@ -2929,6 +3028,7 @@ def MSStruct : InheritableAttr {
let Spellings = [GCC<"ms_struct">];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
let SimpleHandler = 1;
}
def DLLExport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
@ -2977,6 +3077,7 @@ def DLLImportStaticLocal : InheritableAttr, TargetSpecificAttr<TargetWindows> {
def SelectAny : InheritableAttr {
let Spellings = [Declspec<"selectany">, GCC<"selectany">];
let Documentation = [SelectAnyDocs];
let SimpleHandler = 1;
}
def Thread : Attr {
@ -3108,57 +3209,14 @@ def LoopHint : Attr {
llvm_unreachable("Unhandled LoopHint option.");
}
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
unsigned SpellingIndex = getAttributeSpellingListIndex();
// For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
// "nounroll" is already emitted as the pragma name.
if (SpellingIndex == Pragma_nounroll || SpellingIndex == Pragma_nounroll_and_jam)
return;
else if (SpellingIndex == Pragma_unroll || SpellingIndex == Pragma_unroll_and_jam) {
OS << ' ' << getValueString(Policy);
return;
}
assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
OS << ' ' << getOptionName(option) << getValueString(Policy);
}
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const;
// Return a string containing the loop hint argument including the
// enclosing parentheses.
std::string getValueString(const PrintingPolicy &Policy) const {
std::string ValueName;
llvm::raw_string_ostream OS(ValueName);
OS << "(";
if (state == Numeric)
value->printPretty(OS, nullptr, Policy);
else if (state == Enable)
OS << "enable";
else if (state == Full)
OS << "full";
else if (state == AssumeSafety)
OS << "assume_safety";
else
OS << "disable";
OS << ")";
return OS.str();
}
std::string getValueString(const PrintingPolicy &Policy) const;
// Return a string suitable for identifying this attribute in diagnostics.
std::string getDiagnosticName(const PrintingPolicy &Policy) const {
unsigned SpellingIndex = getAttributeSpellingListIndex();
if (SpellingIndex == Pragma_nounroll)
return "#pragma nounroll";
else if (SpellingIndex == Pragma_unroll)
return "#pragma unroll" + (option == UnrollCount ? getValueString(Policy) : "");
else if (SpellingIndex == Pragma_nounroll_and_jam)
return "#pragma nounroll_and_jam";
else if (SpellingIndex == Pragma_unroll_and_jam)
return "#pragma unroll_and_jam" +
(option == UnrollAndJamCount ? getValueString(Policy) : "");
assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
return getOptionName(option) + getValueString(Policy);
}
std::string getDiagnosticName(const PrintingPolicy &Policy) const;
}];
let Documentation = [LoopHintDocs, UnrollHintDocs];
@ -3189,8 +3247,13 @@ def OMPCaptureKind : Attr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
let Args = [UnsignedArgument<"CaptureKind">];
let Args = [UnsignedArgument<"CaptureKindVal">];
let Documentation = [Undocumented];
let AdditionalMembers = [{
llvm::omp::Clause getCaptureKind() const {
return static_cast<llvm::omp::Clause>(getCaptureKindVal());
}
}];
}
def OMPReferencedVar : Attr {
@ -3218,53 +3281,7 @@ def OMPDeclareSimdDecl : Attr {
];
let AdditionalMembers = [{
void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
const {
if (getBranchState() != BS_Undefined)
OS << ' ' << ConvertBranchStateTyToStr(getBranchState());
if (auto *E = getSimdlen()) {
OS << " simdlen(";
E->printPretty(OS, nullptr, Policy);
OS << ")";
}
if (uniforms_size() > 0) {
OS << " uniform";
StringRef Sep = "(";
for (auto *E : uniforms()) {
OS << Sep;
E->printPretty(OS, nullptr, Policy);
Sep = ", ";
}
OS << ")";
}
alignments_iterator NI = alignments_begin();
for (auto *E : aligneds()) {
OS << " aligned(";
E->printPretty(OS, nullptr, Policy);
if (*NI) {
OS << ": ";
(*NI)->printPretty(OS, nullptr, Policy);
}
OS << ")";
++NI;
}
steps_iterator I = steps_begin();
modifiers_iterator MI = modifiers_begin();
for (auto *E : linears()) {
OS << " linear(";
if (*MI != OMPC_LINEAR_unknown)
OS << getOpenMPSimpleClauseTypeName(OMPC_linear, *MI) << "(";
E->printPretty(OS, nullptr, Policy);
if (*MI != OMPC_LINEAR_unknown)
OS << ")";
if (*I) {
OS << ": ";
(*I)->printPretty(OS, nullptr, Policy);
}
OS << ")";
++I;
++MI;
}
}
const;
}];
}
@ -3282,30 +3299,10 @@ def OMPDeclareTargetDecl : InheritableAttr {
[ "DT_Host", "DT_NoHost", "DT_Any" ]>
];
let AdditionalMembers = [{
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
// Use fake syntax because it is for testing and debugging purpose only.
if (getDevType() != DT_Any)
OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
if (getMapType() != MT_To)
OS << ' ' << ConvertMapTypeTyToStr(getMapType());
}
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const;
static llvm::Optional<MapTypeTy>
isDeclareTargetDeclaration(const ValueDecl *VD) {
if (!VD->hasAttrs())
return llvm::None;
if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
return Attr->getMapType();
return llvm::None;
}
static llvm::Optional<DevTypeTy> getDeviceType(const ValueDecl *VD) {
if (!VD->hasAttrs())
return llvm::None;
if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
return Attr->getDevType();
return llvm::None;
}
isDeclareTargetDeclaration(const ValueDecl *VD);
static llvm::Optional<DevTypeTy> getDeviceType(const ValueDecl *VD);
}];
}
@ -3316,14 +3313,16 @@ def OMPAllocateDecl : InheritableAttr {
let Args = [
EnumArgument<"AllocatorType", "AllocatorTypeTy",
[
"omp_default_mem_alloc", "omp_large_cap_mem_alloc",
"omp_const_mem_alloc", "omp_high_bw_mem_alloc",
"omp_low_lat_mem_alloc", "omp_cgroup_mem_alloc",
"omp_pteam_mem_alloc", "omp_thread_mem_alloc", ""
"omp_null_allocator", "omp_default_mem_alloc",
"omp_large_cap_mem_alloc", "omp_const_mem_alloc",
"omp_high_bw_mem_alloc", "omp_low_lat_mem_alloc",
"omp_cgroup_mem_alloc", "omp_pteam_mem_alloc",
"omp_thread_mem_alloc", ""
],
[
"OMPDefaultMemAlloc", "OMPLargeCapMemAlloc",
"OMPConstMemAlloc", "OMPHighBWMemAlloc", "OMPLowLatMemAlloc",
"OMPNullMemAlloc", "OMPDefaultMemAlloc",
"OMPLargeCapMemAlloc", "OMPConstMemAlloc",
"OMPHighBWMemAlloc", "OMPLowLatMemAlloc",
"OMPCGroupMemAlloc", "OMPPTeamMemAlloc", "OMPThreadMemAlloc",
"OMPUserDefinedMemAlloc"
]>,
@ -3341,89 +3340,12 @@ def OMPDeclareVariant : InheritableAttr {
let Documentation = [OMPDeclareVariantDocs];
let Args = [
ExprArgument<"VariantFuncRef">,
VariadicExprArgument<"Scores">,
VariadicUnsignedArgument<"CtxSelectorSets">,
VariadicUnsignedArgument<"CtxSelectors">,
VariadicStringArgument<"ImplVendors">,
VariadicStringArgument<"DeviceKinds">
OMPTraitInfoArgument<"TraitInfos">,
];
let AdditionalMembers = [{
void printScore(raw_ostream & OS, const PrintingPolicy &Policy, unsigned I) const {
if (const Expr *E = *std::next(scores_begin(), I)) {
OS << "score(";
E->printPretty(OS, nullptr, Policy);
OS << "):";
}
}
OMPTraitInfo &getTraitInfo() { return *traitInfos; }
void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
const {
if (const Expr *E = getVariantFuncRef()) {
OS << "(";
E->printPretty(OS, nullptr, Policy);
OS << ")";
}
// TODO: add printing of real context selectors.
OS << " match(";
int Used[OMP_CTX_SET_unknown] = {0};
for (unsigned I = 0, E = ctxSelectorSets_size(); I < E; ++I) {
auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
*std::next(ctxSelectorSets_begin(), I));
if (Used[CtxSet])
continue;
if (I > 0)
OS << ",";
switch (CtxSet) {
case OMP_CTX_SET_implementation:
OS << "implementation={";
break;
case OMP_CTX_SET_device:
OS << "device={";
break;
case OMP_CTX_SET_unknown:
llvm_unreachable("Unknown context selector set.");
}
Used[CtxSet] = 1;
for (unsigned K = I, EK = ctxSelectors_size(); K < EK; ++K) {
auto CtxSetK = static_cast<OpenMPContextSelectorSetKind>(
*std::next(ctxSelectorSets_begin(), K));
if (CtxSet != CtxSetK)
continue;
if (K != I)
OS << ",";
auto Ctx = static_cast<OpenMPContextSelectorKind>(
*std::next(ctxSelectors_begin(), K));
switch (Ctx) {
case OMP_CTX_vendor:
assert(CtxSet == OMP_CTX_SET_implementation &&
"Expected implementation context selector set.");
OS << "vendor(";
printScore(OS, Policy, K);
if (implVendors_size() > 0) {
OS << *implVendors(). begin();
for (StringRef VendorName : llvm::drop_begin(implVendors(), 1))
OS << ", " << VendorName;
}
OS << ")";
break;
case OMP_CTX_kind:
assert(CtxSet == OMP_CTX_SET_device &&
"Expected device context selector set.");
OS << "kind(";
if (deviceKinds_size() > 0) {
OS << *deviceKinds().begin();
for (StringRef KindName : llvm::drop_begin(deviceKinds(), 1))
OS << ", " << KindName;
}
OS << ")";
break;
case OMP_CTX_unknown:
llvm_unreachable("Unknown context selector.");
}
}
OS << "}";
}
OS << ")";
}
const;
}];
}
@ -3438,12 +3360,14 @@ def ExcludeFromExplicitInstantiation : InheritableAttr {
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
let Documentation = [ExcludeFromExplicitInstantiationDocs];
let MeaningfulToClassTemplateDefinition = 1;
let SimpleHandler = 1;
}
def Reinitializes : InheritableAttr {
let Spellings = [Clang<"reinitializes", 0>];
let Subjects = SubjectList<[NonStaticNonConstCXXMethod], ErrorDiag>;
let Documentation = [ReinitializesDocs];
let SimpleHandler = 1;
}
def NoDestroy : InheritableAttr {
@ -3473,9 +3397,16 @@ def NoSpeculativeLoadHardening : InheritableAttr {
def Uninitialized : InheritableAttr {
let Spellings = [Clang<"uninitialized", 0>];
let Subjects = SubjectList<[LocalVar]>;
let PragmaAttributeSupport = 1;
let Documentation = [UninitializedDocs];
}
def LoaderUninitialized : Attr {
let Spellings = [Clang<"loader_uninitialized">];
let Subjects = SubjectList<[GlobalVar]>;
let Documentation = [LoaderUninitializedDocs];
}
def ObjCExternallyRetained : InheritableAttr {
let LangOpts = [ObjCAutoRefCount];
let Spellings = [Clang<"objc_externally_retained">];

View file

@ -140,7 +140,8 @@ def NoEscapeDocs : Documentation {
the compiler that the pointer cannot escape: that is, no reference to the object
the pointer points to that is derived from the parameter value will survive
after the function returns. Users are responsible for making sure parameters
annotated with ``noescape`` do not actuallly escape.
annotated with ``noescape`` do not actually escape. Calling ``free()`` on such
a parameter does not constitute an escape.
For example:
@ -260,6 +261,7 @@ The ``sycl_kernel`` attribute specifies that a function template will be used
to outline device code and to generate an OpenCL kernel.
Here is a code example of the SYCL program, which demonstrates the compiler's
outlining job:
.. code-block:: c++
int foo(int x) { return ++x; }
@ -282,27 +284,29 @@ compilation of functions for the device part can be found in the SYCL 1.2.1
specification Section 6.4.
To show to the compiler entry point to the "device part" of the code, the SYCL
runtime can use the ``sycl_kernel`` attribute in the following way:
.. code-block:: c++
namespace cl {
namespace sycl {
class handler {
template <typename KernelName, typename KernelType/*, ...*/>
__attribute__((sycl_kernel)) void sycl_kernel_function(KernelType KernelFuncObj) {
// ...
KernelFuncObj();
}
template <typename KernelName, typename KernelType, int Dims>
void parallel_for(range<Dims> NumWorkItems, KernelType KernelFunc) {
#ifdef __SYCL_DEVICE_ONLY__
sycl_kernel_function<KernelName, KernelType, Dims>(KernelFunc);
#else
// Host implementation
#endif
}
};
} // namespace sycl
} // namespace cl
.. code-block:: c++
namespace cl {
namespace sycl {
class handler {
template <typename KernelName, typename KernelType/*, ...*/>
__attribute__((sycl_kernel)) void sycl_kernel_function(KernelType KernelFuncObj) {
// ...
KernelFuncObj();
}
template <typename KernelName, typename KernelType, int Dims>
void parallel_for(range<Dims> NumWorkItems, KernelType KernelFunc) {
#ifdef __SYCL_DEVICE_ONLY__
sycl_kernel_function<KernelName, KernelType, Dims>(KernelFunc);
#else
// Host implementation
#endif
}
};
} // namespace sycl
} // namespace cl
The compiler will also generate an OpenCL kernel using the function marked with
the ``sycl_kernel`` attribute.
@ -320,7 +324,7 @@ function marked with the ``sycl_kernel`` attribute:
compiler uses function object type fields to generate OpenCL kernel
parameters.
- The function must return void. The compiler reuses the body of marked functions to
generate the OpenCL kernel body, and the OpenCL kernel must return `void`.
generate the OpenCL kernel body, and the OpenCL kernel must return ``void``.
The SYCL kernel in the previous code sample meets these expectations.
}];
@ -346,6 +350,20 @@ that appears to be capable of returning to its caller.
}];
}
def NoMergeDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
If a statement is marked ``nomerge`` and contains call experessions, those call
expressions inside the statement will not be merged during optimization. This
attribute can be used to prevent the optimizer from obscuring the source
location of certain calls. For example, it will prevent tail merging otherwise
identical code sequences that raise an exception or terminate the program. Tail
merging normally reduces the precision of source location information, making
stack traces less useful for debugging. This attribute gives the user control
over the tradeoff between code size and debug information precision.
}];
}
def AssertCapabilityDocs : Documentation {
let Category = DocCatFunction;
let Heading = "assert_capability, assert_shared_capability";
@ -481,7 +499,7 @@ parameter.
Note that this attribute merely informs the compiler that a function always
returns a sufficiently aligned pointer. It does not cause the compiler to
emit code to enforce that alignment. The behavior is undefined if the returned
poitner is not sufficiently aligned.
pointer is not sufficiently aligned.
}];
}
@ -939,11 +957,11 @@ The behavior of a function with respect to reference counting for Foundation
convention (e.g. functions starting with "get" are assumed to return at
``+0``).
It can be overriden using a family of the following attributes. In
It can be overridden using a family of the following attributes. In
Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to
a function communicates that the object is returned at ``+1``, and the caller
is responsible for freeing it.
Similiarly, the annotation ``__attribute__((ns_returns_not_retained))``
Similarly, the annotation ``__attribute__((ns_returns_not_retained))``
specifies that the object is returned at ``+0`` and the ownership remains with
the callee.
The annotation ``__attribute__((ns_consumes_self))`` specifies that
@ -1159,7 +1177,7 @@ def ObjCRuntimeNameDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
By default, the Objective-C interface or protocol identifier is used
in the metadata name for that object. The `objc_runtime_name`
in the metadata name for that object. The ``objc_runtime_name``
attribute allows annotated interfaces or protocols to use the
specified string argument in the object's metadata name instead of the
default name.
@ -1287,7 +1305,7 @@ correspond to different platforms. For most platforms, the availability
attribute with the platform corresponding to the target platform will be used;
any others will be ignored. However, the availability for ``watchOS`` and
``tvOS`` can be implicitly inferred from an ``iOS`` availability attribute.
Any explicit availability attributes for those platforms are still prefered over
Any explicit availability attributes for those platforms are still preferred over
the implicitly inferred availability attributes. If no availability attribute
specifies availability for the current target platform, the availability
attributes are ignored. Supported platforms are:
@ -1395,7 +1413,7 @@ pragma rather than using the inferred ``iOS`` availability from the declaration:
void getsThePragmaTVOSAvailabilityAttribute(void) __attribute__((availability(iOS,introduced=11.0)));
#pragma clang attribute pop
The compiler is also able to apply implicly inferred attributes from a pragma
The compiler is also able to apply implicitly inferred attributes from a pragma
as well. For example, when targeting ``tvOS``, the function below will receive
a ``tvOS`` availability attribute that is implicitly inferred from the ``iOS``
availability attribute applied by the pragma:
@ -1563,7 +1581,7 @@ expression are discarded under suspicious circumstances. A diagnostic is
generated when a function or its return type is marked with ``[[nodiscard]]``
(or ``__attribute__((warn_unused_result))``) and the function call appears as a
potentially-evaluated discarded-value expression that is not explicitly cast to
`void`.
``void``.
A string literal may optionally be provided to the attribute, which will be
reproduced in any resulting diagnostics. Redeclarations using different forms
@ -1713,7 +1731,7 @@ def BPFPreserveAccessIndexDocs : Documentation {
Clang supports the ``__attribute__((preserve_access_index))``
attribute for the BPF target. This attribute may be attached to a
struct or union declaration, where if -g is specified, it enables
preserving struct or union member access debuginfo indicies of this
preserving struct or union member access debuginfo indices of this
struct or union, similar to clang ``__builtin_preserve_acceess_index()``.
}];
}
@ -1729,7 +1747,7 @@ directly as an interrupt service routine.
By default, the compiler will produce a function prologue and epilogue suitable for
an interrupt service routine that handles an External Interrupt Controller (eic)
generated interrupt. This behaviour can be explicitly requested with the "eic"
generated interrupt. This behavior can be explicitly requested with the "eic"
argument.
Otherwise, for use with vectored interrupt mode, the argument passed should be
@ -1767,7 +1785,7 @@ Clang supports the GNU style ``__attribute__((micromips))`` and
may be attached to a function definition and instructs the backend to generate
or not to generate microMIPS code for that function.
These attributes override the `-mmicromips` and `-mno-micromips` options
These attributes override the ``-mmicromips`` and ``-mno-micromips`` options
on the command line.
}];
}
@ -2764,11 +2782,13 @@ The ``trivial_abi`` attribute can be applied to a C++ class, struct, or union.
It instructs the compiler to pass and return the type using the C ABI for the
underlying type when the type would otherwise be considered non-trivial for the
purpose of calls.
A class annotated with `trivial_abi` can have non-trivial destructors or copy/move constructors without automatically becoming non-trivial for the purposes of calls. For example:
A class annotated with ``trivial_abi`` can have non-trivial destructors or
copy/move constructors without automatically becoming non-trivial for the
purposes of calls. For example:
.. code-block:: c++
// A is trivial for the purposes of calls because `trivial_abi` makes the
// A is trivial for the purposes of calls because ``trivial_abi`` makes the
// user-provided special functions trivial.
struct __attribute__((trivial_abi)) A {
~A();
@ -2790,6 +2810,7 @@ destroy the object before returning.
Attribute ``trivial_abi`` has no effect in the following cases:
- The class directly declares a virtual base or virtual methods.
- Copy constructors and move constructors of the class are all deleted.
- The class has a base class that is non-trivial for the purposes of calls.
- The class has a non-static data member whose type is non-trivial for the purposes of calls, which includes:
@ -3296,15 +3317,15 @@ def OMPDeclareSimdDocs : Documentation {
let Category = DocCatFunction;
let Heading = "#pragma omp declare simd";
let Content = [{
The `declare simd` construct can be applied to a function to enable the creation
The ``declare simd`` construct can be applied to a function to enable the creation
of one or more versions that can process multiple arguments using SIMD
instructions from a single invocation in a SIMD loop. The `declare simd`
directive is a declarative directive. There may be multiple `declare simd`
directives for a function. The use of a `declare simd` construct on a function
instructions from a single invocation in a SIMD loop. The ``declare simd``
directive is a declarative directive. There may be multiple ``declare simd``
directives for a function. The use of a ``declare simd`` construct on a function
enables the creation of SIMD versions of the associated function that can be
used to process multiple arguments from a single invocation from a SIMD loop
concurrently.
The syntax of the `declare simd` construct is as follows:
The syntax of the ``declare simd`` construct is as follows:
.. code-block:: none
@ -3331,7 +3352,7 @@ def OMPDeclareTargetDocs : Documentation {
let Category = DocCatFunction;
let Heading = "#pragma omp declare target";
let Content = [{
The `declare target` directive specifies that variables and functions are mapped
The ``declare target`` directive specifies that variables and functions are mapped
to a device for OpenMP offload mechanism.
The syntax of the declare target directive is as follows:
@ -3369,10 +3390,10 @@ def OMPDeclareVariantDocs : Documentation {
let Category = DocCatFunction;
let Heading = "#pragma omp declare variant";
let Content = [{
The `declare variant` directive declares a specialized variant of a base
function and specifies the context in which that specialized variant is used.
The declare variant directive is a declarative directive.
The syntax of the `declare variant` construct is as follows:
The ``declare variant`` directive declares a specialized variant of a base
function and specifies the context in which that specialized variant is used.
The declare variant directive is a declarative directive.
The syntax of the ``declare variant`` construct is as follows:
.. code-block:: none
@ -3387,8 +3408,23 @@ where clause is one of the following:
match(context-selector-specification)
and where `variant-func-id` is the name of a function variant that is either a
base language identifier or, for C++, a template-id.
and where ``variant-func-id`` is the name of a function variant that is either a
base language identifier or, for C++, a template-id.
Clang provides the following context selector extensions, used via
``implementation={extension(EXTENSION)}``:
.. code-block:: none
match_all
match_any
match_none
The match extensions change when the *entire* context selector is considered a
match for an OpenMP context. The default is ``all``, with ``none`` no trait in the
selector is allowed to be in the OpenMP context, with ``any`` a single trait in
both the selector and OpenMP context is sufficient. Only a single match
extension trait is allowed per context selector.
}];
}
@ -3473,7 +3509,7 @@ def NoThrowDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Clang supports the GNU style ``__attribute__((nothrow))`` and Microsoft style
``__declspec(nothrow)`` attribute as an equivalent of `noexcept` on function
``__declspec(nothrow)`` attribute as an equivalent of ``noexcept`` on function
declarations. This attribute informs the compiler that the annotated function
does not throw an exception. This prevents exception-unwinding. This attribute
is particularly useful on functions in the C Standard Library that are
@ -3676,7 +3712,7 @@ using the Swift calling convention for a function or function pointer.
The lowering for the Swift calling convention, as described by the Swift
ABI documentation, occurs in multiple phases. The first, "high-level"
phase breaks down the formal parameters and results into innately direct
and indirect components, adds implicit paraameters for the generic
and indirect components, adds implicit parameters for the generic
signature, and assigns the context and error ABI treatments to parameters
where applicable. The second phase breaks down the direct parameters
and results from the first phase and assigns them to registers or the
@ -3718,7 +3754,7 @@ of the first phase, as follows:
``swiftcall`` does not support variadic arguments or unprototyped functions.
The parameter ABI treatment attributes are aspects of the function type.
A function type which which applies an ABI treatment attribute to a
A function type which applies an ABI treatment attribute to a
parameter is a different type from an otherwise-identical function type
that does not. A single parameter may not have multiple ABI treatment
attributes.
@ -3847,7 +3883,7 @@ with different ABI versions supported. For example, a newer version of a class
could have a different set of data members and thus have a different size. Using
the ``abi_tag`` attribute, it is possible to have different mangled names for
a global variable of the class type. Therefore, the old code could keep using
the old manged name and the new code will use the new mangled name with tags.
the old mangled name and the new code will use the new mangled name with tags.
}];
}
@ -3873,10 +3909,10 @@ that have a hot path and a cold path. The hot path is usually a small piece
of code that doesn't use many registers. The cold path might need to call out to
another function and therefore only needs to preserve the caller-saved
registers, which haven't already been saved by the caller. The
`preserve_most` calling convention is very similar to the ``cold`` calling
``preserve_most`` calling convention is very similar to the ``cold`` calling
convention in terms of caller/callee-saved registers, but they are used for
different types of function calls. ``coldcc`` is for function calls that are
rarely executed, whereas `preserve_most` function calls are intended to be
rarely executed, whereas ``preserve_most`` function calls are intended to be
on the hot path and definitely executed a lot. Furthermore ``preserve_most``
doesn't prevent the inliner from inlining the function call.
@ -3930,11 +3966,11 @@ Consider the function declaration for a hypothetical function ``f``:
void f(void) __attribute__((deprecated("message", "replacement")));
When spelled as `__attribute__((deprecated))`, the deprecated attribute can have
When spelled as ``__attribute__((deprecated))``, the deprecated attribute can have
two optional string arguments. The first one is the message to display when
emitting the warning; the second one enables the compiler to provide a Fix-It
to replace the deprecated name with a new name. Otherwise, when spelled as
`[[gnu::deprecated]] or [[deprecated]]`, the attribute can have one optional
``[[gnu::deprecated]]`` or ``[[deprecated]]``, the attribute can have one optional
string argument which is the message to display when emitting the warning.
}];
}
@ -4001,9 +4037,9 @@ takes precedence over the command line option ``-fpatchable-function-entry=N,M``
def TransparentUnionDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
This attribute can be applied to a union to change the behaviour of calls to
This attribute can be applied to a union to change the behavior of calls to
functions that have an argument with a transparent union type. The compiler
behaviour is changed in the following manner:
behavior is changed in the following manner:
- A value whose type is any member of the transparent union can be passed as an
argument without the need to cast that value.
@ -4033,7 +4069,7 @@ initialized classes. A non-lazy class will be initialized eagerly when the
Objective-C runtime is loaded. This is required for certain system classes which
have instances allocated in non-standard ways, such as the classes for blocks
and constant strings. Adding this attribute is essentially equivalent to
providing a trivial `+load` method but avoids the (fairly small) load-time
providing a trivial ``+load`` method but avoids the (fairly small) load-time
overheads associated with defining and calling such a method.
}];
}
@ -4073,8 +4109,8 @@ ways:
including calling the ``+initialize`` method if present.
- The implicit ``_cmd`` parameter containing the method's selector is still defined.
In order to minimize code-size costs, the implementation will not emit a reference
to the selector if the parameter is unused within the method.
In order to minimize code-size costs, the implementation will not emit a reference
to the selector if the parameter is unused within the method.
Symbols for direct method implementations are implicitly given hidden
visibility, meaning that they can only be called within the same linkage unit.
@ -4115,7 +4151,7 @@ documentation for more information.
def ObjCDirectMembersDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
The ``objc_direct_members`` attribute can be placed on an Objective-C
The ``objc_direct_members`` attribute can be placed on an Objective-C
``@interface`` or ``@implementation`` to mark that methods declared
therein should be considered direct by default. See the documentation
for ``objc_direct`` for more information about direct methods.
@ -4124,9 +4160,7 @@ When ``objc_direct_members`` is placed on an ``@interface`` block, every
method in the block is considered to be declared as direct. This includes any
implicit method declarations introduced by property declarations. If the method
redeclares a non-direct method, the declaration is ill-formed, exactly as if the
method was annotated with the ``objc_direct`` attribute. ``objc_direct_members``
cannot be placed on the primary interface of a class, only on category or class
extension interfaces.
method was annotated with the ``objc_direct`` attribute.
When ``objc_direct_members`` is placed on an ``@implementation`` block,
methods defined in the block are considered to be declared as direct unless
@ -4329,7 +4363,7 @@ with this attribute. This is because previously constructed subobjects need to
be destroyed if an exception gets thrown before the initialization of the
complete object is complete. For instance:
.. code-block::c++
.. code-block:: c++
void f() {
try {
@ -4340,7 +4374,7 @@ complete object is complete. For instance:
}
}
Here, if the construction of `array[9]` fails with an exception, `array[0..8]`
Here, if the construction of ``array[9]`` fails with an exception, ``array[0..8]``
will be destroyed, so the element's destructor needs to be accessible.
}];
}
@ -4357,6 +4391,29 @@ it rather documents the programmer's intent.
}];
}
def LoaderUninitializedDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
The ``loader_uninitialized`` attribute can be placed on global variables to
indicate that the variable does not need to be zero initialized by the loader.
On most targets, zero-initialization does not incur any additional cost.
For example, most general purpose operating systems deliberately ensure
that all memory is properly initialized in order to avoid leaking privileged
information from the kernel or other programs. However, some targets
do not make this guarantee, and on these targets, avoiding an unnecessary
zero-initialization can have a significant impact on load times and/or code
size.
A declaration with this attribute is a non-tentative definition just as if it
provided an initializer. Variables with this attribute are considered to be
uninitialized in the same sense as a local variable, and the programs must
write to them before reading from them. If the variable's type is a C++ class
type with a non-trivial default constructor, or an array thereof, this attribute
only suppresses the static zero-initialization of the variable, not the dynamic
initialization provided by executing the default constructor.
}];
}
def CallbackDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@ -4366,7 +4423,7 @@ arguments, are identified by their parameter name or position (starting with
1!) in the annotated function. The first position in the attribute identifies
the callback callee, the following positions declare describe its arguments.
The callback callee is required to be callable with the number, and order, of
the specified arguments. The index `0`, or the identifier `this`, is used to
the specified arguments. The index ``0``, or the identifier ``this``, is used to
represent an implicit "this" pointer in class methods. If there is no implicit
"this" pointer it shall not be referenced. The index '-1', or the name "__",
represents an unknown callback callee argument. This can be a value which is
@ -4383,13 +4440,13 @@ position, it is undefined if that parameter is used for anything other than the
actual callback. Inspected, captured, or modified parameters shall not be
listed in the ``callback`` metadata.
Example encodings for the callback performed by `pthread_create` are shown
Example encodings for the callback performed by ``pthread_create`` are shown
below. The explicit attribute annotation indicates that the third parameter
(`start_routine`) is called zero or more times by the `pthread_create` function,
and that the fourth parameter (`arg`) is passed along. Note that the callback
behavior of `pthread_create` is automatically recognized by Clang. In addition,
the declarations of `__kmpc_fork_teams` and `__kmpc_fork_call`, generated for
`#pragma omp target teams` and `#pragma omp parallel`, respectively, are also
(``start_routine``) is called zero or more times by the ``pthread_create`` function,
and that the fourth parameter (``arg``) is passed along. Note that the callback
behavior of ``pthread_create`` is automatically recognized by Clang. In addition,
the declarations of ``__kmpc_fork_teams`` and ``__kmpc_fork_call``, generated for
``#pragma omp target teams`` and ``#pragma omp parallel``, respectively, are also
automatically recognized as broker functions. Further functions might be added
in the future.
@ -4514,7 +4571,7 @@ 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,
non-externally-retained behavior for that parameter. For instance,
``first_param`` is externally-retained below, but not ``second_param``:
.. code-block:: objc
@ -4536,7 +4593,7 @@ def MIGConventionDocs : Documentation {
The Mach Interface Generator release-on-success convention dictates
functions that follow it to only release arguments passed to them when they
return "success" (a ``kern_return_t`` error code that indicates that
no errors have occured). Otherwise the release is performed by the MIG client
no errors have occurred). Otherwise the release is performed by the MIG client
that called the function. The annotation ``__attribute__((mig_server_routine))``
is applied in order to specify which functions are expected to follow the
convention. This allows the Static Analyzer to find bugs caused by violations of
@ -4588,15 +4645,25 @@ only call one function.
}];
}
def HIPPinnedShadowDocs : Documentation {
def CUDADeviceBuiltinSurfaceTypeDocs : Documentation {
let Category = DocCatType;
let Content = [{
The GNU style attribute __attribute__((hip_pinned_shadow)) or MSVC style attribute
__declspec(hip_pinned_shadow) can be added to the definition of a global variable
to indicate it is a HIP pinned shadow variable. A HIP pinned shadow variable can
be accessed on both device side and host side. It has external linkage and is
not initialized on device side. It has internal linkage and is initialized by
the initializer on host side.
The ``device_builtin_surface_type`` attribute can be applied to a class
template when declaring the surface reference. A surface reference variable
could be accessed on the host side and, on the device side, might be translated
into an internal surface object, which is established through surface bind and
unbind runtime APIs.
}];
}
def CUDADeviceBuiltinTextureTypeDocs : Documentation {
let Category = DocCatType;
let Content = [{
The ``device_builtin_texture_type`` attribute can be applied to a class
template when declaring the texture reference. A texture reference variable
could be accessed on the host side and, on the device side, might be translated
into an internal texture object, which is established through texture bind and
unbind runtime APIs.
}];
}
@ -4609,7 +4676,7 @@ def LifetimeOwnerDocs : Documentation {
The attribute ``[[gsl::Owner(T)]]`` applies to structs and classes that own an
object of type ``T``:
.. code-block:: c++
.. code::
class [[gsl::Owner(int)]] IntOwner {
private:
@ -4635,7 +4702,7 @@ def LifetimePointerDocs : Documentation {
The attribute ``[[gsl::Pointer(T)]]`` applies to structs and classes that behave
like pointers to an object of type ``T``:
.. code-block:: c++
.. code::
class [[gsl::Pointer(int)]] IntPointer {
private:
@ -4668,11 +4735,11 @@ When the Owner's lifetime ends, it will consider the Pointer to be dangling.
}];
}
def ArmMveAliasDocs : Documentation {
def ArmBuiltinAliasDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
This attribute is used in the implementation of the ACLE intrinsics
for the Arm MVE instruction set. It allows the intrinsic functions to
This attribute is used in the implementation of the ACLE intrinsics.
It allows the intrinsic functions to
be declared using the names defined in ACLE, and still be recognized
as clang builtins equivalent to the underlying name. For example,
``arm_mve.h`` declares the function ``vaddq_u32`` with
@ -4683,8 +4750,8 @@ recognized as that clang builtin, and in the latter case, the choice
of which builtin to identify the function as can be deferred until
after overload resolution.
This attribute can only be used to set up the aliases for the MVE
intrinsic functions; it is intended for use only inside ``arm_mve.h``,
This attribute can only be used to set up the aliases for certain Arm
intrinsic functions; it is intended for use only inside ``arm_*.h``
and is not a general mechanism for declaring arbitrary aliases for
clang builtin functions.
}];
@ -4694,7 +4761,7 @@ def NoBuiltinDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
.. Note:: This attribute is not yet fully implemented, it is validated but has
no effect on the generated code.
no effect on the generated code.
The ``__attribute__((no_builtin))`` is similar to the ``-fno-builtin`` flag
except it is specific to the body of a function. The attribute may also be
@ -4765,7 +4832,7 @@ def UseHandleDocs : Documentation {
let Category = HandleDocs;
let Content = [{
A function taking a handle by value might close the handle. If a function
parameter is annotated with `use_handle` it is assumed to not to change
parameter is annotated with ``use_handle`` it is assumed to not to change
the state of the handle. It is also assumed to require an open handle to work with.
.. code-block:: c++
@ -4779,7 +4846,7 @@ the state of the handle. It is also assumed to require an open handle to work wi
def ReleaseHandleDocs : Documentation {
let Category = HandleDocs;
let Content = [{
If a function parameter is annotated with `release_handle` it is assumed to
If a function parameter is annotated with ``release_handle`` it is assumed to
close the handle. It is also assumed to require an open handle to work with.
.. code-block:: c++
@ -4787,3 +4854,70 @@ close the handle. It is also assumed to require an open handle to work with.
zx_status_t zx_handle_close(zx_handle_t handle [[clang::release_handle]]);
}];
}
def ArmMveStrictPolymorphismDocs : Documentation {
let Category = DocCatType;
let Content = [{
This attribute is used in the implementation of the ACLE intrinsics for the Arm
MVE instruction set. It is used to define the vector types used by the MVE
intrinsics.
Its effect is to modify the behavior of a vector type with respect to function
overloading. If a candidate function for overload resolution has a parameter
type with this attribute, then the selection of that candidate function will be
disallowed if the actual argument can only be converted via a lax vector
conversion. The aim is to prevent spurious ambiguity in ARM MVE polymorphic
intrinsics.
.. code-block:: c++
void overloaded(uint16x8_t vector, uint16_t scalar);
void overloaded(int32x4_t vector, int32_t scalar);
uint16x8_t myVector;
uint16_t myScalar;
// myScalar is promoted to int32_t as a side effect of the addition,
// so if lax vector conversions are considered for myVector, then
// the two overloads are equally good (one argument conversion
// each). But if the vector has the __clang_arm_mve_strict_polymorphism
// attribute, only the uint16x8_t,uint16_t overload will match.
overloaded(myVector, myScalar + 1);
However, this attribute does not prohibit lax vector conversions in contexts
other than overloading.
.. code-block:: c++
uint16x8_t function();
// This is still permitted with lax vector conversion enabled, even
// if the vector types have __clang_arm_mve_strict_polymorphism
int32x4_t result = function();
}];
}
def ArmCmseNSCallDocs : Documentation {
let Category = DocCatType;
let Content = [{
This attribute declares a non-secure function type. When compiling for secure
state, a call to such a function would switch from secure to non-secure state.
All non-secure function calls must happen only through a function pointer, and
a non-secure function type should only be used as a base type of a pointer.
See `ARMv8-M Security Extensions: Requirements on Development
Tools - Engineering Specification Documentation
<https://developer.arm.com/docs/ecm0359818/latest/>`_ for more information.
}];
}
def ArmCmseNSEntryDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
This attribute declares a function that can be called from non-secure state, or
from secure state. Entering from and returning to non-secure state would switch
to and from secure state, respectively, and prevent flow of information
to non-secure state, except via return values. See `ARMv8-M Security Extensions:
Requirements on Development Tools - Engineering Specification Documentation
<https://developer.arm.com/docs/ecm0359818/latest/>`_ for more information.
}];
}

View file

@ -134,6 +134,11 @@ public:
const IdentifierInfo *getScopeName() const { return ScopeName; }
SourceLocation getScopeLoc() const { return ScopeLoc; }
/// Gets the normalized full name, which consists of both scope and name and
/// with surrounding underscores removed as appropriate (e.g.
/// __gnu__::__attr__ will be normalized to gnu::attr).
std::string getNormalizedFullName() const;
bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }

View file

@ -36,6 +36,7 @@
// a -> __builtin_va_list
// A -> "reference" to __builtin_va_list
// V -> Vector, followed by the number of elements and the base type.
// q -> Scalable vector, followed by the number of elements and the base type.
// E -> ext_vector, followed by the number of elements and the base type.
// X -> _Complex, followed by the base type.
// Y -> ptrdiff_t
@ -64,6 +65,7 @@
// & -> reference (optionally followed by an address space number)
// C -> const
// D -> volatile
// R -> restrict
// The third value provided to the macro specifies information about attributes
// of the function. These must be kept in sync with the predicates in the
@ -322,6 +324,9 @@ BUILTIN(__builtin_truncf, "ff", "Fnc")
BUILTIN(__builtin_truncl, "LdLd", "Fnc")
BUILTIN(__builtin_truncf16, "hh", "Fnc")
// Access to floating point environment
BUILTIN(__builtin_flt_rounds, "i", "n")
// C99 complex builtins
BUILTIN(__builtin_cabs, "dXd", "Fne")
BUILTIN(__builtin_cabsf, "fXf", "Fne")
@ -471,7 +476,7 @@ BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin_va_start, "vA.", "nt")
BUILTIN(__builtin_va_end, "vA", "n")
BUILTIN(__builtin_va_copy, "vAA", "n")
BUILTIN(__builtin_stdarg_start, "vA.", "n")
BUILTIN(__builtin_stdarg_start, "vA.", "nt")
BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc")
BUILTIN(__builtin_bcmp, "ivC*vC*z", "Fn")
BUILTIN(__builtin_bcopy, "vv*v*z", "n")
@ -480,6 +485,7 @@ BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:")
BUILTIN(__builtin_memchr, "v*vC*iz", "nF")
BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF")
BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memcpy_inline, "vv*vC*Iz", "nt")
BUILTIN(__builtin_memmove, "v*v*vC*z", "nF")
BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memset, "v*v*iz", "nF")
@ -515,7 +521,6 @@ BUILTIN(__builtin_return_address, "v*IUi", "n")
BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
BUILTIN(__builtin_frame_address, "v*IUi", "n")
BUILTIN(__builtin___clear_cache, "vc*c*", "n")
BUILTIN(__builtin_flt_rounds, "i", "nc")
BUILTIN(__builtin_setjmp, "iv**", "j")
BUILTIN(__builtin_longjmp, "vv**i", "r")
BUILTIN(__builtin_unwind_init, "v", "")
@ -562,6 +567,7 @@ BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
BUILTIN(__builtin_unpredictable, "LiLi" , "nc")
BUILTIN(__builtin_expect, "LiLiLi" , "nc")
BUILTIN(__builtin_expect_with_probability, "LiLiLid", "nc")
BUILTIN(__builtin_prefetch, "vvC*.", "nc")
BUILTIN(__builtin_readcyclecounter, "ULLi", "n")
BUILTIN(__builtin_trap, "v", "nr")
@ -573,6 +579,10 @@ BUILTIN(__builtin_alloca, "v*z" , "Fn")
BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn")
BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
BUILTIN(__builtin_matrix_transpose, "v.", "nFt")
BUILTIN(__builtin_matrix_column_major_load, "v.", "nFt")
BUILTIN(__builtin_matrix_column_major_store, "v.", "nFt")
// "Overloaded" Atomic operator builtins. These are overloaded to support data
// types of i8, i16, i32, i64, and i128. The front-end sees calls to the
// non-suffixed version of these (which has a bogus type) and transforms them to
@ -722,7 +732,7 @@ ATOMIC_BUILTIN(__c11_atomic_fetch_max, "v.", "t")
ATOMIC_BUILTIN(__c11_atomic_fetch_min, "v.", "t")
BUILTIN(__c11_atomic_thread_fence, "vi", "n")
BUILTIN(__c11_atomic_signal_fence, "vi", "n")
BUILTIN(__c11_atomic_is_lock_free, "iz", "n")
BUILTIN(__c11_atomic_is_lock_free, "bz", "n")
// GNU atomic builtins.
ATOMIC_BUILTIN(__atomic_load, "v.", "t")
@ -751,8 +761,8 @@ BUILTIN(__atomic_test_and_set, "bvD*i", "n")
BUILTIN(__atomic_clear, "vvD*i", "n")
BUILTIN(__atomic_thread_fence, "vi", "n")
BUILTIN(__atomic_signal_fence, "vi", "n")
BUILTIN(__atomic_always_lock_free, "izvCD*", "n")
BUILTIN(__atomic_is_lock_free, "izvCD*", "n")
BUILTIN(__atomic_always_lock_free, "bzvCD*", "n")
BUILTIN(__atomic_is_lock_free, "bzvCD*", "n")
// OpenCL 2.0 atomic builtins.
ATOMIC_BUILTIN(__opencl_atomic_init, "v.", "t")

View file

@ -33,6 +33,10 @@ BUILTIN(__builtin_amdgcn_workitem_id_x, "Ui", "nc")
BUILTIN(__builtin_amdgcn_workitem_id_y, "Ui", "nc")
BUILTIN(__builtin_amdgcn_workitem_id_z, "Ui", "nc")
BUILTIN(__builtin_amdgcn_workgroup_size_x, "Us", "nc")
BUILTIN(__builtin_amdgcn_workgroup_size_y, "Us", "nc")
BUILTIN(__builtin_amdgcn_workgroup_size_z, "Us", "nc")
BUILTIN(__builtin_amdgcn_mbcnt_hi, "UiUiUi", "nc")
BUILTIN(__builtin_amdgcn_mbcnt_lo, "UiUiUi", "nc")
@ -40,6 +44,7 @@ BUILTIN(__builtin_amdgcn_mbcnt_lo, "UiUiUi", "nc")
// Instruction builtins.
//===----------------------------------------------------------------------===//
BUILTIN(__builtin_amdgcn_s_getreg, "UiIi", "n")
BUILTIN(__builtin_amdgcn_s_setreg, "vIiUi", "n")
BUILTIN(__builtin_amdgcn_s_getpc, "LUi", "n")
BUILTIN(__builtin_amdgcn_s_waitcnt, "vIi", "n")
BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n")
@ -53,6 +58,13 @@ BUILTIN(__builtin_amdgcn_ds_gws_barrier, "vUiUi", "n")
BUILTIN(__builtin_amdgcn_ds_gws_sema_v, "vUi", "n")
BUILTIN(__builtin_amdgcn_ds_gws_sema_br, "vUiUi", "n")
BUILTIN(__builtin_amdgcn_ds_gws_sema_p, "vUi", "n")
BUILTIN(__builtin_amdgcn_fence, "vUicC*", "n")
BUILTIN(__builtin_amdgcn_atomic_inc32, "UZiUZiD*UZiUicC*", "n")
BUILTIN(__builtin_amdgcn_atomic_inc64, "UWiUWiD*UWiUicC*", "n")
BUILTIN(__builtin_amdgcn_atomic_dec32, "UZiUZiD*UZiUicC*", "n")
BUILTIN(__builtin_amdgcn_atomic_dec64, "UWiUWiD*UWiUicC*", "n")
// FIXME: Need to disallow constant address space.
BUILTIN(__builtin_amdgcn_div_scale, "dddbb*", "n")
@ -65,6 +77,8 @@ BUILTIN(__builtin_amdgcn_trig_preop, "ddi", "nc")
BUILTIN(__builtin_amdgcn_trig_preopf, "ffi", "nc")
BUILTIN(__builtin_amdgcn_rcp, "dd", "nc")
BUILTIN(__builtin_amdgcn_rcpf, "ff", "nc")
BUILTIN(__builtin_amdgcn_sqrt, "dd", "nc")
BUILTIN(__builtin_amdgcn_sqrtf, "ff", "nc")
BUILTIN(__builtin_amdgcn_rsq, "dd", "nc")
BUILTIN(__builtin_amdgcn_rsqf, "ff", "nc")
BUILTIN(__builtin_amdgcn_rsq_clamp, "dd", "nc")
@ -150,6 +164,7 @@ BUILTIN(__builtin_amdgcn_interp_mov, "fUiUiUiUi", "nc")
TARGET_BUILTIN(__builtin_amdgcn_div_fixuph, "hhhh", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_rcph, "hh", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_sqrth, "hh", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_rsqh, "hh", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_sinh, "hh", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_cosh, "hh", "nc", "16-bit-insts")
@ -212,5 +227,30 @@ BUILTIN(__builtin_r600_read_tidig_z, "Ui", "nc")
BUILTIN(__builtin_r600_recipsqrt_ieee, "dd", "nc")
BUILTIN(__builtin_r600_recipsqrt_ieeef, "ff", "nc")
//===----------------------------------------------------------------------===//
// MFMA builtins.
//===----------------------------------------------------------------------===//
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x1f32, "V32fffV32fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x1f32, "V16fffV16fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_4x4x1f32, "V4fffV4fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x2f32, "V16fffV16fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x4f32, "V4fffV4fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x4f16, "V32fV4hV4hV32fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x4f16, "V16fV4hV4hV16fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_4x4x4f16, "V4fV4hV4hV4fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x8f16, "V16fV4hV4hV16fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x16f16, "V4fV4hV4hV4fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_32x32x4i8, "V32iiiV32iIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_16x16x4i8, "V16iiiV16iIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_4x4x4i8, "V4iiiV4iIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_32x32x8i8, "V16iiiV16iIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_16x16x16i8, "V4iiiV4iIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x2bf16, "V32fV2sV2sV32fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x2bf16, "V16fV2sV2sV16fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_4x4x2bf16, "V4fV2sV2sV4fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x4bf16, "V16fV2sV2sV16fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x8bf16, "V4fV2sV2sV4fIiIiIi", "nc", "mai-insts")
#undef BUILTIN
#undef TARGET_BUILTIN

View file

@ -202,6 +202,8 @@ BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
// aren't included from both here and BuiltinsAArch64.def.)
#include "clang/Basic/arm_mve_builtins.inc"
#include "clang/Basic/arm_cde_builtins.inc"
// MSVC
LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)

View file

@ -20,5 +20,8 @@
// Get record field information.
TARGET_BUILTIN(__builtin_preserve_field_info, "Ui.", "t", "")
// Get BTF type id.
TARGET_BUILTIN(__builtin_btf_type_id, "Ui.", "t", "")
#undef BUILTIN
#undef TARGET_BUILTIN

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,206 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Automatically generated file, do not edit!
//===----------------------------------------------------------------------===//
CUSTOM_BUILTIN_MAPPING(M2_mpysmi, 0)
CUSTOM_BUILTIN_MAPPING(M2_dpmpyss_s0, 0)
CUSTOM_BUILTIN_MAPPING(M2_dpmpyuu_s0, 0)
CUSTOM_BUILTIN_MAPPING(M2_mpyi, 0)
CUSTOM_BUILTIN_MAPPING(M2_mpyui, 0)
CUSTOM_BUILTIN_MAPPING(A2_add, 0)
CUSTOM_BUILTIN_MAPPING(A2_sub, 0)
CUSTOM_BUILTIN_MAPPING(A2_addi, 0)
CUSTOM_BUILTIN_MAPPING(A2_addp, 0)
CUSTOM_BUILTIN_MAPPING(A2_subp, 0)
CUSTOM_BUILTIN_MAPPING(A2_neg, 0)
CUSTOM_BUILTIN_MAPPING(A2_zxtb, 0)
CUSTOM_BUILTIN_MAPPING(A2_sxtb, 0)
CUSTOM_BUILTIN_MAPPING(A2_zxth, 0)
CUSTOM_BUILTIN_MAPPING(A2_sxth, 0)
CUSTOM_BUILTIN_MAPPING(A2_and, 0)
CUSTOM_BUILTIN_MAPPING(A2_or, 0)
CUSTOM_BUILTIN_MAPPING(A2_xor, 0)
CUSTOM_BUILTIN_MAPPING(A2_not, 0)
CUSTOM_BUILTIN_MAPPING(A2_subri, 0)
CUSTOM_BUILTIN_MAPPING(A2_andir, 0)
CUSTOM_BUILTIN_MAPPING(A2_orir, 0)
CUSTOM_BUILTIN_MAPPING(S2_asr_i_r, 0)
CUSTOM_BUILTIN_MAPPING(S2_lsr_i_r, 0)
CUSTOM_BUILTIN_MAPPING(S2_asl_i_r, 0)
CUSTOM_BUILTIN_MAPPING(S2_asr_i_p, 0)
CUSTOM_BUILTIN_MAPPING(S2_lsr_i_p, 0)
CUSTOM_BUILTIN_MAPPING(S2_asl_i_p, 0)
CUSTOM_BUILTIN_MAPPING(V6_vS32b_qpred_ai, 64)
CUSTOM_BUILTIN_MAPPING(V6_vS32b_qpred_ai_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vS32b_nqpred_ai, 64)
CUSTOM_BUILTIN_MAPPING(V6_vS32b_nqpred_ai_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vS32b_nt_qpred_ai, 64)
CUSTOM_BUILTIN_MAPPING(V6_vS32b_nt_qpred_ai_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vS32b_nt_nqpred_ai, 64)
CUSTOM_BUILTIN_MAPPING(V6_vS32b_nt_nqpred_ai_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vaddbq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vaddbq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vsubbq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vsubbq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vaddbnq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vaddbnq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vsubbnq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vsubbnq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vaddhq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vaddhq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vsubhq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vsubhq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vaddhnq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vaddhnq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vsubhnq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vsubhnq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vaddwq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vaddwq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vsubwq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vsubwq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vaddwnq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vaddwnq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vsubwnq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vsubwnq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vandqrt, 64)
CUSTOM_BUILTIN_MAPPING(V6_vandqrt_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vandqrt_acc, 64)
CUSTOM_BUILTIN_MAPPING(V6_vandqrt_acc_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vandvrt, 64)
CUSTOM_BUILTIN_MAPPING(V6_vandvrt_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vandvrt_acc, 64)
CUSTOM_BUILTIN_MAPPING(V6_vandvrt_acc_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtw, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtw_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtw_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtw_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtw_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtw_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtw_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtw_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqw, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqw_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqw_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqw_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqw_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqw_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqw_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqw_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgth, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgth_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgth_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgth_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgth_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgth_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgth_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgth_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqh, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqh_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqh_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqh_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqh_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqh_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqh_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqh_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtb, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtb_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtb_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtb_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtb_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtb_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtb_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtb_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqb, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqb_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqb_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqb_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqb_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqb_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_veqb_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_veqb_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtuw, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtuw_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtuw_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtuw_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtuw_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtuw_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtuw_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtuw_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtuh, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtuh_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtuh_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtuh_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtuh_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtuh_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtuh_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtuh_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtub, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtub_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtub_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtub_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtub_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtub_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgtub_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgtub_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_pred_or, 64)
CUSTOM_BUILTIN_MAPPING(V6_pred_or_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_pred_and, 64)
CUSTOM_BUILTIN_MAPPING(V6_pred_and_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_pred_not, 64)
CUSTOM_BUILTIN_MAPPING(V6_pred_not_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_pred_xor, 64)
CUSTOM_BUILTIN_MAPPING(V6_pred_xor_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_pred_and_n, 64)
CUSTOM_BUILTIN_MAPPING(V6_pred_and_n_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_pred_or_n, 64)
CUSTOM_BUILTIN_MAPPING(V6_pred_or_n_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_pred_scalar2, 64)
CUSTOM_BUILTIN_MAPPING(V6_pred_scalar2_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vmux, 64)
CUSTOM_BUILTIN_MAPPING(V6_vmux_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vswap, 64)
CUSTOM_BUILTIN_MAPPING(V6_vswap_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vaddcarry, 64)
CUSTOM_BUILTIN_MAPPING(V6_vaddcarry_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vsubcarry, 64)
CUSTOM_BUILTIN_MAPPING(V6_vsubcarry_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vandnqrt, 64)
CUSTOM_BUILTIN_MAPPING(V6_vandnqrt_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vandnqrt_acc, 64)
CUSTOM_BUILTIN_MAPPING(V6_vandnqrt_acc_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vandvqv, 64)
CUSTOM_BUILTIN_MAPPING(V6_vandvqv_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vandvnqv, 64)
CUSTOM_BUILTIN_MAPPING(V6_vandvnqv_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_pred_scalar2v2, 64)
CUSTOM_BUILTIN_MAPPING(V6_pred_scalar2v2_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_shuffeqw, 64)
CUSTOM_BUILTIN_MAPPING(V6_shuffeqw_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_shuffeqh, 64)
CUSTOM_BUILTIN_MAPPING(V6_shuffeqh_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgathermwq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgathermwq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgathermhq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgathermhq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vgathermhwq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vgathermhwq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vscattermwq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vscattermwq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vscattermhq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vscattermhq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vscattermhwq, 64)
CUSTOM_BUILTIN_MAPPING(V6_vscattermhwq_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vprefixqb, 64)
CUSTOM_BUILTIN_MAPPING(V6_vprefixqb_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vprefixqh, 64)
CUSTOM_BUILTIN_MAPPING(V6_vprefixqh_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vprefixqw, 64)
CUSTOM_BUILTIN_MAPPING(V6_vprefixqw_128B, 128)
CUSTOM_BUILTIN_MAPPING(V6_vaddcarrysat, 64)
CUSTOM_BUILTIN_MAPPING(V6_vaddcarrysat_128B, 128)

View file

@ -635,6 +635,9 @@ BUILTIN(__builtin_msa_ld_h, "V8Ssv*Ii", "nc")
BUILTIN(__builtin_msa_ld_w, "V4Siv*Ii", "nc")
BUILTIN(__builtin_msa_ld_d, "V2SLLiv*Ii", "nc")
BUILTIN(__builtin_msa_ldr_d, "V2SLLiv*Ii", "nc")
BUILTIN(__builtin_msa_ldr_w, "V4Siv*Ii", "nc")
BUILTIN(__builtin_msa_ldi_b, "V16cIi", "nc")
BUILTIN(__builtin_msa_ldi_h, "V8sIi", "nc")
BUILTIN(__builtin_msa_ldi_w, "V4iIi", "nc")
@ -857,6 +860,9 @@ BUILTIN(__builtin_msa_st_h, "vV8Ssv*Ii", "nc")
BUILTIN(__builtin_msa_st_w, "vV4Siv*Ii", "nc")
BUILTIN(__builtin_msa_st_d, "vV2SLLiv*Ii", "nc")
BUILTIN(__builtin_msa_str_d, "vV2SLLiv*Ii", "nc")
BUILTIN(__builtin_msa_str_w, "vV4Siv*Ii", "nc")
BUILTIN(__builtin_msa_subs_s_b, "V16ScV16ScV16Sc", "nc")
BUILTIN(__builtin_msa_subs_s_h, "V8SsV8SsV8Ss", "nc")
BUILTIN(__builtin_msa_subs_s_w, "V4SiV4SiV4Si", "nc")

View file

@ -20,7 +20,9 @@
#pragma push_macro("SM_70")
#pragma push_macro("SM_72")
#pragma push_macro("SM_75")
#define SM_75 "sm_75"
#pragma push_macro("SM_80")
#define SM_80 "sm_80"
#define SM_75 "sm_75|" SM_80
#define SM_72 "sm_72|" SM_75
#define SM_70 "sm_70|" SM_72
@ -31,7 +33,11 @@
#pragma push_macro("PTX61")
#pragma push_macro("PTX63")
#pragma push_macro("PTX64")
#define PTX64 "ptx64"
#pragma push_macro("PTX65")
#pragma push_macro("PTX70")
#define PTX70 "ptx70"
#define PTX65 "ptx65|" PTX70
#define PTX64 "ptx64|" PTX65
#define PTX63 "ptx63|" PTX64
#define PTX61 "ptx61|" PTX63
#define PTX60 "ptx60|" PTX61
@ -721,7 +727,10 @@ TARGET_BUILTIN(__imma_m8n8k32_st_c_i32, "vi*iC*UiIi", "", AND(SM_75,PTX63))
#pragma pop_macro("SM_70")
#pragma pop_macro("SM_72")
#pragma pop_macro("SM_75")
#pragma pop_macro("SM_80")
#pragma pop_macro("PTX60")
#pragma pop_macro("PTX61")
#pragma pop_macro("PTX63")
#pragma pop_macro("PTX64")
#pragma pop_macro("PTX65")
#pragma pop_macro("PTX70")

View file

@ -298,6 +298,44 @@ BUILTIN(__builtin_altivec_vrldmi, "V2ULLiV2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vrlwnm, "V4UiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_vrldnm, "V2ULLiV2ULLiV2ULLi", "")
// P10 Vector Parallel Bits built-ins.
BUILTIN(__builtin_altivec_vpdepd, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vpextd, "V2ULLiV2ULLiV2ULLi", "")
// P10 Vector Centrifuge built-in.
BUILTIN(__builtin_altivec_vcfuged, "V2ULLiV2ULLiV2ULLi", "")
// P10 Vector Gather Every N-th Bit built-in.
BUILTIN(__builtin_altivec_vgnb, "ULLiV1ULLLiIi", "")
// P10 Vector Clear Bytes built-ins.
BUILTIN(__builtin_altivec_vclrlb, "V16cV16cUi", "")
BUILTIN(__builtin_altivec_vclrrb, "V16cV16cUi", "")
// P10 Vector Count Leading / Trailing Zeroes under bit Mask built-ins.
BUILTIN(__builtin_altivec_vclzdm, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vctzdm, "V2ULLiV2ULLiV2ULLi", "")
// P10 Vector Shift built-ins.
BUILTIN(__builtin_altivec_vsldbi, "V16UcV16UcV16UcIi", "")
BUILTIN(__builtin_altivec_vsrdbi, "V16UcV16UcV16UcIi", "")
// P10 Vector Insert built-ins.
BUILTIN(__builtin_altivec_vinsblx, "V16UcV16UcULLiULLi", "")
BUILTIN(__builtin_altivec_vinsbrx, "V16UcV16UcULLiULLi", "")
BUILTIN(__builtin_altivec_vinshlx, "V8UsV8UsULLiULLi", "")
BUILTIN(__builtin_altivec_vinshrx, "V8UsV8UsULLiULLi", "")
BUILTIN(__builtin_altivec_vinswlx, "V4UiV4UiULLiULLi", "")
BUILTIN(__builtin_altivec_vinswrx, "V4UiV4UiULLiULLi", "")
BUILTIN(__builtin_altivec_vinsdlx, "V2ULLiV2ULLiULLiULLi", "")
BUILTIN(__builtin_altivec_vinsdrx, "V2ULLiV2ULLiULLiULLi", "")
BUILTIN(__builtin_altivec_vinsbvlx, "V16UcV16UcULLiV16Uc", "")
BUILTIN(__builtin_altivec_vinsbvrx, "V16UcV16UcULLiV16Uc", "")
BUILTIN(__builtin_altivec_vinshvlx, "V8UsV8UsULLiV8Us", "")
BUILTIN(__builtin_altivec_vinshvrx, "V8UsV8UsULLiV8Us", "")
BUILTIN(__builtin_altivec_vinswvlx, "V4UiV4UiULLiV4Ui", "")
BUILTIN(__builtin_altivec_vinswvrx, "V4UiV4UiULLiV4Ui", "")
// VSX built-ins.
BUILTIN(__builtin_vsx_lxvd2x, "V2divC*", "")
@ -391,6 +429,11 @@ BUILTIN(__builtin_vsx_xvcpsgnsp, "V4fV4fV4f", "")
BUILTIN(__builtin_vsx_xvabssp, "V4fV4f", "")
BUILTIN(__builtin_vsx_xvabsdp, "V2dV2d", "")
BUILTIN(__builtin_vsx_xxgenpcvbm, "V16UcV16Uci", "")
BUILTIN(__builtin_vsx_xxgenpcvhm, "V8UsV8Usi", "")
BUILTIN(__builtin_vsx_xxgenpcvwm, "V4UiV4Uii", "")
BUILTIN(__builtin_vsx_xxgenpcvdm, "V2ULLiV2ULLii", "")
// vector Insert/Extract exponent/significand builtins
BUILTIN(__builtin_vsx_xviexpdp, "V2dV2ULLiV2ULLi", "")
BUILTIN(__builtin_vsx_xviexpsp, "V4fV4UiV4Ui", "")
@ -422,6 +465,19 @@ BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "")
BUILTIN(__builtin_vsx_xxpermdi, "v.", "t")
BUILTIN(__builtin_vsx_xxsldwi, "v.", "t")
BUILTIN(__builtin_vsx_xxeval, "V2ULLiV2ULLiV2ULLiV2ULLiIi", "")
BUILTIN(__builtin_vsx_xvtlsbb, "iV16Ucb", "")
// P10 Vector Permute Extended built-in.
BUILTIN(__builtin_vsx_xxpermx, "V16UcV16UcV16UcV16UcIi", "")
// P10 Vector Blend built-ins.
BUILTIN(__builtin_vsx_xxblendvb, "V16UcV16UcV16UcV16Uc", "")
BUILTIN(__builtin_vsx_xxblendvh, "V8UsV8UsV8UsV8Us", "")
BUILTIN(__builtin_vsx_xxblendvw, "V4UiV4UiV4UiV4Ui", "")
BUILTIN(__builtin_vsx_xxblendvd, "V2ULLiV2ULLiV2ULLiV2ULLi", "")
// Float 128 built-ins
BUILTIN(__builtin_sqrtf128_round_to_odd, "LLdLLd", "")
BUILTIN(__builtin_addf128_round_to_odd, "LLdLLdLLd", "")
@ -470,6 +526,11 @@ BUILTIN(__builtin_divweu, "UiUiUi", "")
BUILTIN(__builtin_divde, "SLLiSLLiSLLi", "")
BUILTIN(__builtin_divdeu, "ULLiULLiULLi", "")
BUILTIN(__builtin_bpermd, "SLLiSLLiSLLi", "")
BUILTIN(__builtin_pdepd, "ULLiULLiULLi", "")
BUILTIN(__builtin_pextd, "ULLiULLiULLi", "")
BUILTIN(__builtin_cfuged, "ULLiULLiULLi", "")
BUILTIN(__builtin_cntlzdm, "ULLiULLiULLi", "")
BUILTIN(__builtin_cnttzdm, "ULLiULLiULLi", "")
// Vector int128 (un)pack
BUILTIN(__builtin_unpack_vector_int128, "ULLiV1LLLii", "")

View file

@ -0,0 +1,20 @@
//===--- BuiltinsSVE.def - SVE Builtin function database --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the SVE-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.
#define GET_SVE_BUILTINS
#include "clang/Basic/arm_sve_builtins.inc"
#undef GET_SVE_BUILTINS
#undef BUILTIN

View file

@ -25,10 +25,6 @@
BUILTIN(__builtin_wasm_memory_size, "zIi", "n")
BUILTIN(__builtin_wasm_memory_grow, "zIiz", "n")
// Bulk memory builtins
TARGET_BUILTIN(__builtin_wasm_memory_init, "vIUiIUiv*UiUi", "", "bulk-memory")
TARGET_BUILTIN(__builtin_wasm_data_drop, "vIUi", "", "bulk-memory")
// Thread-local storage
TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory")
TARGET_BUILTIN(__builtin_wasm_tls_align, "z", "nc", "bulk-memory")
@ -45,9 +41,9 @@ TARGET_BUILTIN(__builtin_wasm_throw, "vIUiv*", "r", "exception-handling")
TARGET_BUILTIN(__builtin_wasm_rethrow_in_catch, "v", "r", "exception-handling")
// Atomic wait and notify.
BUILTIN(__builtin_wasm_atomic_wait_i32, "ii*iLLi", "n")
BUILTIN(__builtin_wasm_atomic_wait_i64, "iLLi*LLiLLi", "n")
BUILTIN(__builtin_wasm_atomic_notify, "Uii*Ui", "n")
TARGET_BUILTIN(__builtin_wasm_atomic_wait_i32, "ii*iLLi", "n", "atomics")
TARGET_BUILTIN(__builtin_wasm_atomic_wait_i64, "iLLi*LLiLLi", "n", "atomics")
TARGET_BUILTIN(__builtin_wasm_atomic_notify, "Uii*Ui", "n", "atomics")
// Trapping fp-to-int conversions
BUILTIN(__builtin_wasm_trunc_s_i32_f32, "if", "nc")
@ -70,23 +66,23 @@ TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i64_f64, "LLid", "nc", "nontrappi
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i64_f64, "LLid", "nc", "nontrapping-fptoint")
// SIMD builtins
TARGET_BUILTIN(__builtin_wasm_swizzle_v8x16, "V16cV16cV16c", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_swizzle_v8x16, "V16cV16cV16c", "nc", "simd128")
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_u_i8x16, "iV16cIi", "nc", "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_u_i16x8, "iV8sIi", "nc", "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_i64x2, "LLiV2LLiIi", "nc", "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_extract_lane_f64x2, "dV2dIi", "nc", "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_i64x2, "V2LLiV2LLiIiLLi", "nc", "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_replace_lane_f64x2, "V2dV2dIid", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_add_saturate_s_i8x16, "V16cV16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_add_saturate_u_i8x16, "V16cV16cV16c", "nc", "simd128")
@ -98,10 +94,28 @@ TARGET_BUILTIN(__builtin_wasm_sub_saturate_u_i8x16, "V16cV16cV16c", "nc", "simd1
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_avgr_u_i8x16, "V16cV16cV16c", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_avgr_u_i16x8, "V8sV8sV8s", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_abs_i8x16, "V16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_abs_i16x8, "V8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_abs_i32x4, "V4iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_s_i8x16, "V16cV16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_u_i8x16, "V16cV16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_max_s_i8x16, "V16cV16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_max_u_i8x16, "V16cV16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_s_i16x8, "V8sV8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_u_i16x8, "V8sV8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_max_s_i16x8, "V8sV8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_max_u_i16x8, "V8sV8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_s_i32x4, "V4iV4iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_u_i32x4, "V4iV4iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_max_s_i32x4, "V4iV4iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_max_u_i32x4, "V4iV4iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_avgr_u_i8x16, "V16cV16cV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_avgr_u_i16x8, "V8sV8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_bitselect, "V4iV4iV4iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_shuffle_v8x16, "V16cV16cV16cIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_any_true_i8x16, "iV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_any_true_i16x8, "iV8s", "nc", "simd128")
@ -112,28 +126,43 @@ 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_bitmask_i8x16, "iV16c", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_bitmask_i16x8, "iV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_bitmask_i32x4, "iV4i", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_abs_f32x4, "V4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_abs_f64x2, "V2dV2d", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_abs_f64x2, "V2dV2d", "nc", "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_pmin_f32x4, "V4fV4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_pmax_f32x4, "V4fV4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_f64x2, "V2dV2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_pmin_f64x2, "V2dV2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_pmax_f64x2, "V2dV2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_ceil_f32x4, "V4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_floor_f32x4, "V4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_trunc_f32x4, "V4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_nearest_f32x4, "V4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_ceil_f64x2, "V2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_floor_f64x2, "V2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_trunc_f64x2, "V2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_nearest_f64x2, "V2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_dot_s_i32x4_i16x8, "V4iV8sV8s", "nc", "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_sqrt_f32x4, "V4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_sqrt_f64x2, "V2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_qfma_f32x4, "V4fV4fV4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_qfms_f32x4, "V4fV4fV4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_qfma_f32x4, "V4fV4fV4fV4f", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_qfms_f32x4, "V4fV4fV4fV4f", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_qfma_f64x2, "V2dV2dV2dV2d", "nc", "unimplemented-simd128")
TARGET_BUILTIN(__builtin_wasm_qfms_f64x2, "V2dV2dV2dV2d", "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")
TARGET_BUILTIN(__builtin_wasm_narrow_s_i8x16_i16x8, "V16cV8sV8s", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_narrow_u_i8x16_i16x8, "V16cV8sV8s", "nc", "simd128")

View file

@ -1900,6 +1900,13 @@ TARGET_BUILTIN(__builtin_ia32_invpcid, "vUiv*", "nc", "invpcid")
TARGET_BUILTIN(__builtin_ia32_enqcmd, "Ucv*vC*", "n", "enqcmd")
TARGET_BUILTIN(__builtin_ia32_enqcmds, "Ucv*vC*", "n", "enqcmd")
// SERIALIZE
TARGET_BUILTIN(__builtin_ia32_serialize, "v", "n", "serialize")
// TSXLDTRK
TARGET_BUILTIN(__builtin_ia32_xsusldtrk, "v", "n", "tsxldtrk")
TARGET_BUILTIN(__builtin_ia32_xresldtrk, "v", "n", "tsxldtrk")
// MSVC
TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
@ -1927,6 +1934,15 @@ TARGET_HEADER_BUILTIN(__readgsword, "UsUNi", "nh", "intrin.h", ALL_MS_LANGUAGES
TARGET_HEADER_BUILTIN(__readgsdword, "UNiUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsqword, "ULLiUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "WiWiD*Wi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "WiWiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64, "WiWiD*Wi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64, "WiWiD*Wi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeSub64, "WiWiD*Wi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "WiWiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64, "WiWiD*Wi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64, "WiWiD*Wi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
#undef BUILTIN
#undef TARGET_BUILTIN
#undef TARGET_HEADER_BUILTIN

View file

@ -33,14 +33,6 @@ TARGET_HEADER_BUILTIN(__faststorefence, "v", "nh", "intrin.h", ALL_MS_LANGUAGES,
TARGET_HEADER_BUILTIN(__shiftleft128, "ULLiULLiULLiUc", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__shiftright128, "ULLiULLiULLiUc", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeSub64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange128, "UcLLiD*LLiLLiLLi*", "nh", "intrin.h", ALL_MS_LANGUAGES, "cx16")
TARGET_BUILTIN(__builtin_ia32_readeflags_u64, "UOi", "n", "")
@ -101,6 +93,22 @@ TARGET_BUILTIN(__builtin_ia32_cvtsi2ss64, "V4fV4fOiIi", "ncV:128:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dUOiIi", "ncV:128:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fUOiIi", "ncV:128:", "avx512f")
TARGET_BUILTIN(__builtin_ia32_directstore_u64, "vULi*ULi", "n", "movdiri")
// AMX
TARGET_BUILTIN(__builtin_ia32_tile_loadconfig, "vvC*", "n", "amx-tile")
TARGET_BUILTIN(__builtin_ia32_tile_storeconfig, "vvC*", "n", "amx-tile")
TARGET_BUILTIN(__builtin_ia32_tilerelease, "v", "n", "amx-tile")
TARGET_BUILTIN(__builtin_ia32_tilezero, "vUc", "n", "amx-tile")
TARGET_BUILTIN(__builtin_ia32_tileloadd64, "vIUcvC*z", "n", "amx-tile")
TARGET_BUILTIN(__builtin_ia32_tileloaddt164, "vIUcvC*z", "n", "amx-tile")
TARGET_BUILTIN(__builtin_ia32_tilestored64, "vIUcv*z", "n", "amx-tile")
TARGET_BUILTIN(__builtin_ia32_tdpbssd, "vIUcIUcIUc", "n", "amx-int8")
TARGET_BUILTIN(__builtin_ia32_tdpbsud, "vIUcIUcIUc", "n", "amx-int8")
TARGET_BUILTIN(__builtin_ia32_tdpbusd, "vIUcIUcIUc", "n", "amx-int8")
TARGET_BUILTIN(__builtin_ia32_tdpbuud, "vIUcIUcIUc", "n", "amx-int8")
TARGET_BUILTIN(__builtin_ia32_tdpbf16ps, "vIUcIUcIUc", "n", "amx-bf16")
TARGET_BUILTIN(__builtin_ia32_ptwrite64, "vUOi", "n", "ptwrite")
#undef BUILTIN

View file

@ -39,15 +39,15 @@ CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe
CODEGENOPT(Backchain , 1, 0) ///< -mbackchain
CODEGENOPT(ControlFlowGuardNoChecks , 1, 0) ///< -cfguard-no-checks
CODEGENOPT(ControlFlowGuard , 1, 0) ///< -cfguard
CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files.
CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files.
CODEGENOPT(CoverageExitBlockBeforeBody, 1, 0) ///< Whether to emit the exit block before the body blocks in GCNO files.
CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors.
CODEGENOPT(RegisterGlobalDtorsWithAtExit, 1, 1) ///< Use atexit or __cxa_atexit to register global destructors.
CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker
///< aliases to base ctors when possible.
CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled.
CODEGENOPT(UniqueSectionNames, 1, 1) ///< Set for -funique-section-names.
CODEGENOPT(UniqueBasicBlockSectionNames, 1, 1) ///< Set for -funique-basic-block-section-names,
///< Produce unique section names with
///< basic block sections.
ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none
CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory.
@ -58,12 +58,15 @@ CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get
///< frontend.
CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers
CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0
CODEGENOPT(ExperimentalStrictFloatingPoint, 1, 0) ///< Enables the new, experimental
///< strict floating point.
CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental
///< pass manager.
CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
///< pass manager.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
CODEGENOPT(EnableDebugEntryValues, 1, 0) ///< Emit call site parameter dbg info
CODEGENOPT(EmitCallSiteInfo, 1, 0) ///< Emit call site info only in the case of
///< '-g' + 'O>0' level.
CODEGENOPT(IndirectTlsSegRefs, 1, 0) ///< Set when -mno-tls-direct-seg-refs
///< is specified.
CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
@ -106,6 +109,13 @@ CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0)
///< Set when -fxray-always-emit-typedevents is enabled.
CODEGENOPT(XRayAlwaysEmitTypedEvents , 1, 0)
///< Set when -fxray-ignore-loops is enabled.
CODEGENOPT(XRayIgnoreLoops , 1, 0)
///< Set with -fno-xray-function-index to omit the index section.
CODEGENOPT(XRayOmitFunctionIndex , 1, 0)
///< Set the minimum number of instructions in a function to determine selective
///< XRay instrumentation.
VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200)
@ -146,16 +156,11 @@ CODEGENOPT(NoWarn , 1, 0) ///< Set when -Wa,--no-warn is enabled.
CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
CODEGENOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain
///< inline line tables.
CODEGENOPT(StackClashProtector, 1, 0) ///< Set when -fstack-clash-protection is enabled.
CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled.
CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf.
CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero
CODEGENOPT(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined.
CODEGENOPT(Reassociate , 1, 0) ///< Allow reassociation of FP math ops
CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated.
CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled.
CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN.
CODEGENOPT(FlushDenorm , 1, 0) ///< Allow FP denorm numbers to be flushed to zero
CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt
CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Internal Linkage symbols get unique names.
/// When false, this attempts to generate code as if the result of an
/// overflowing conversion matches the overflowing behavior of a target's native
@ -227,6 +232,7 @@ CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing
CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard
///< in sanitizer coverage.
CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters.
CODEGENOPT(SanitizeCoverageInlineBoolFlag, 1, 0) ///< Use inline bool flag.
CODEGENOPT(SanitizeCoveragePCTable, 1, 0) ///< Create a PC Table.
CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning.
CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing
@ -244,7 +250,6 @@ VALUE_CODEGENOPT(TimeTraceGranularity, 32, 500) ///< Minimum time granularity (i
CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled.
CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled.
CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled.
CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns.
CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables.
CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer.
CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer.
@ -301,6 +306,9 @@ CODEGENOPT(LTOVisibilityPublicStd, 1, 0)
/// or 0 if unspecified.
VALUE_CODEGENOPT(NumRegisterParameters, 32, 0)
/// The threshold to put data into small data section.
VALUE_CODEGENOPT(SmallDataLimit, 32, 0)
/// The lower bound for a buffer to be considered for stack protection.
VALUE_CODEGENOPT(SSPBufferSize, 32, 0)
@ -378,14 +386,12 @@ CODEGENOPT(ForceEmitVTables, 1, 0)
/// Whether to emit an address-significance table into the object file.
CODEGENOPT(Addrsig, 1, 0)
ENUM_CODEGENOPT(SignReturnAddress, SignReturnAddressScope, 2, SignReturnAddressScope::None)
ENUM_CODEGENOPT(SignReturnAddressKey, SignReturnAddressKeyValue, 1, SignReturnAddressKeyValue::AKey)
CODEGENOPT(BranchTargetEnforcement, 1, 0)
/// Whether to emit unused static constants.
CODEGENOPT(KeepStaticConsts, 1, 0)
/// Whether to not follow the AAPCS that enforce at least one read before storing to a volatile bitfield
CODEGENOPT(ForceAAPCSBitfieldLoad, 1, 0)
#undef CODEGENOPT
#undef ENUM_CODEGENOPT
#undef VALUE_CODEGENOPT

View file

@ -110,13 +110,21 @@ public:
Embed_Marker // Embed a marker as a placeholder for bitcode.
};
enum class SignReturnAddressScope {
None, // No signing for any function
NonLeaf, // Sign the return address of functions that spill LR
All // Sign the return address of all functions
};
enum class SignReturnAddressKeyValue { AKey, BKey };
// This field stores one of the allowed values for the option
// -fbasic-block-sections=. The allowed values with this option are:
// {"labels", "all", "list=<file>", "none"}.
//
// "labels": Only generate basic block symbols (labels) for all basic
// blocks, do not generate unique sections for basic blocks.
// Use the machine basic block id in the symbol name to
// associate profile info from virtual address to machine
// basic block.
// "all" : Generate basic block sections for all basic blocks.
// "list=<file>": Generate basic block sections for a subset of basic blocks.
// The functions and the machine basic block ids are specified
// in the file.
// "none": Disable sections/labels for basic blocks.
std::string BBSections;
enum class FramePointerKind {
None, // Omit all frame pointers.
@ -164,7 +172,10 @@ public:
std::string FloatABI;
/// The floating-point denormal mode to use.
llvm::DenormalMode FPDenormalMode = llvm::DenormalMode::Invalid;
llvm::DenormalMode FPDenormalMode = llvm::DenormalMode::getIEEE();
/// The floating-point denormal mode to use, for float.
llvm::DenormalMode FP32DenormalMode = llvm::DenormalMode::getIEEE();
/// The float precision limit to use, if non-empty.
std::string LimitFloatPrecision;
@ -311,6 +322,21 @@ public:
/// List of dynamic shared object files to be loaded as pass plugins.
std::vector<std::string> PassPlugins;
/// Path to allowlist file specifying which objects
/// (files, functions) should exclusively be instrumented
/// by sanitizer coverage pass.
std::vector<std::string> SanitizeCoverageAllowlistFiles;
/// Path to blocklist file specifying which objects
/// (files, functions) listed for instrumentation by sanitizer
/// coverage pass should actually not be instrumented.
std::vector<std::string> SanitizeCoverageBlocklistFiles;
/// Executable and command-line used to create a given CompilerInvocation.
/// Most of the time this will be the full -cc1 command.
const char *Argv0 = nullptr;
ArrayRef<const char *> CommandLineArgs;
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)

Some files were not shown because too many files have changed in this diff Show more