mirror of
https://github.com/opnsense/src.git
synced 2026-06-04 06:15:33 -04:00
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:
commit
5ffd83dbcc
6179 changed files with 461071 additions and 218666 deletions
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -193,4 +193,4 @@ public:
|
|||
|
||||
} // clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_ASTCONCEPT_H
|
||||
#endif // LLVM_CLANG_AST_ASTCONCEPT_H
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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">;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
194
contrib/llvm-project/clang/include/clang/AST/ComputeDependence.h
Normal file
194
contrib/llvm-project/clang/include/clang/AST/ComputeDependence.h
Normal 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
|
||||
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ namespace llvm {
|
|||
return clang::DeclGroupRef::getFromOpaquePtr(P);
|
||||
}
|
||||
|
||||
enum { NumLowBitsAvailable = 0 };
|
||||
static constexpr int NumLowBitsAvailable = 0;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
284
contrib/llvm-project/clang/include/clang/AST/DependenceFlags.h
Normal file
284
contrib/llvm-project/clang/include/clang/AST/DependenceFlags.h
Normal 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
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
144
contrib/llvm-project/clang/include/clang/AST/ParentMapContext.h
Normal file
144
contrib/llvm-project/clang/include/clang/AST/ParentMapContext.h
Normal 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
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}]>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ public:
|
|||
ET_RegistryNotBindable = 4,
|
||||
ET_RegistryAmbiguousOverload = 5,
|
||||
ET_RegistryValueNotFound = 6,
|
||||
ET_RegistryUnknownEnumWithReplace = 7,
|
||||
|
||||
ET_ParserStringError = 100,
|
||||
ET_ParserNoOpenParen = 101,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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(); }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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 *;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -168,4 +168,4 @@ protected:
|
|||
};
|
||||
|
||||
} // end namespace clang
|
||||
#endif
|
||||
#endif // LLVM_CLANG_ANALYSES_DATAFLOW_VALUES
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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">];
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
}];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
File diff suppressed because it is too large
Load diff
|
|
@ -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)
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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", "")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue